Compare commits

...

6 Commits

14 changed files with 710 additions and 398 deletions

View File

@@ -1,6 +1,7 @@
# 할 일 및 이슈 # 할 일 및 이슈
## 중기 개선 ## 중기 개선
- 라이트모드/다크모드 2차 보정까지 반영했으므로, 남은 작업은 전체 화면을 실제 사용 흐름으로 돌려 보며 대비·명도·아이콘 가독성을 미세하게 QA하는 최종 테마 점검 단계로 가져간다.
- 관리자용 티어표 승인/숨김 처리, 아이템 정렬 UI를 추가한다. - 관리자용 티어표 승인/숨김 처리, 아이템 정렬 UI를 추가한다.
- 회원 일괄 작업(다중 선택, 일괄 비밀번호 초기화, 활동 저조 계정 정리) 같은 관리 보조 기능을 추가한다. - 회원 일괄 작업(다중 선택, 일괄 비밀번호 초기화, 활동 저조 계정 정리) 같은 관리 보조 기능을 추가한다.
- 티어 행 프리셋 저장, 색상 관리, 행 복제 같은 고급 편집 기능을 추가한다. - 티어 행 프리셋 저장, 색상 관리, 행 복제 같은 고급 편집 기능을 추가한다.
@@ -8,4 +9,4 @@
- 업로드 파일은 MIME 타입뿐 아니라 파일 시그니처 기반 검증까지 확장한다. - 업로드 파일은 MIME 타입뿐 아니라 파일 시그니처 기반 검증까지 확장한다.
- production에서 SESSION_SECRET 누락 시 서버가 부팅되지 않도록 강제한다. - production에서 SESSION_SECRET 누락 시 서버가 부팅되지 않도록 강제한다.
- helmet 기반 보안 헤더와 업로드 정적 응답 헤더를 정리한다. - helmet 기반 보안 헤더와 업로드 정적 응답 헤더를 정리한다.
- 책 아이콘 기반 사용법 모달은 구조를 먼저 붙였으므로, 실제 16:9 스크린샷 자산과 단계별 문구를 운영 톤에 맞게 채운다. - 책 아이콘 기반 사용법 모달은 제작 흐름뿐 아니라 복사, 템플릿 업데이트 요청, 새 템플릿 요청까지 확장했으므로, 실제 16:9 스크린샷 자산과 단계별 문구를 운영 톤에 맞게 채운다.

View File

@@ -1,5 +1,30 @@
# 업데이트 로그 # 업데이트 로그
## 2026-04-01 v1.3.33
- 라이트모드/다크모드 2차 보정으로 관리자 화면과 티어 에디터의 카드, 패널, 입력창, 모달, 썸네일 프레임을 전역 테마 변수 기준으로 다시 맞춰, 후속 화면에서도 명도 차가 더 자연스럽게 이어지도록 정리함.
- 공통 셸도 함께 손봐서 좌측 사이드 아이콘 필터와 텍스트 대비를 테마 변수 기반으로 전환하고, 가이드 모달·축소 검색 모달·내비 활성 상태까지 라이트모드에서 읽기 쉬운 톤으로 보정함.
- 전역 스타일 변수의 다크 기본값과 아이콘 필터 값을 바로잡아, 카드 배경과 텍스트 변수의 자기참조/오동작 가능성을 줄이고 이후 테마 QA 기준을 더 안정적으로 맞춤.
## 2026-04-01 v1.3.32
- 전역 테마 변수와 로컬 저장 기반 테마 토글을 추가해, Settings 화면 오른쪽 사이드에서 라이트모드/다크모드를 전환하고 재방문 시 같은 테마를 유지할 수 있게 함.
- 앱 셸, 홈, 게임 허브, 내 티어표, 즐겨찾기, 검색, 로그인, 설정 화면의 공통 카드·입력·텍스트 색을 테마 변수 기준으로 바꿔, 주요 사용자 화면은 라이트/다크 전환이 자연스럽게 이어지도록 1차 정리함.
- 관리자 화면과 티어 에디터처럼 스타일 밀도가 높은 화면은 후속 단계에서 세부 톤을 더 정교하게 맞추도록 todo 기준도 갱신함.
## 2026-04-01 v1.3.31
- 관리자 게임 관리의 오른쪽 사이드 게임 선택 리스트는 더 많은 항목을 한 번에 볼 수 있도록 최대 높이를 늘리고, 게임 카드 내부 간격도 사용자가 조정한 CSS 기준으로 반영해 목록 밀도를 다시 다듬음.
## 2026-04-01 v1.3.30
- 헤더의 `Tier Maker` 로고는 레인보우 그라데이션 텍스트로 바꿔 서비스 첫인상이 더 또렷하게 보이도록 정리하고, `by zenn`은 새 창으로 프로필 페이지를 여는 외부 링크로 연결함.
- 다음 단계 작업용으로 라이트모드/다크모드 전환 항목을 todo 문서에 추가해, 현재의 다크 톤 UI를 유지하면서도 이후 테마 확장 흐름을 공식 작업 목록에 올림.
## 2026-04-01 v1.3.29
- 책 아이콘 사용법 모달 진입점은 항상 보이는 오른쪽 사이드 하단 버튼 대신, Settings 화면에서만 왼쪽 사이드 하단의 보조 액션 버튼으로 옮겨 더 필요할 때만 찾게 되는 문맥형 진입 방식으로 정리함.
- 인증 스토어에 초기 세션 동기화 완료 상태를 추가하고, 앱 셸·로그인 화면·프로필 화면은 세션 확인 전까지 비로그인 UI를 먼저 그리지 않도록 보강해 첫 진입 시 화면이 갑자기 로그인 상태로 뒤집히는 플래시를 줄임.
## 2026-04-01 v1.3.28
- 책 아이콘 기반 사용법 모달은 기존의 단순 제작 흐름 안내를 넘어, 다른 사람 티어표 복사, 템플릿 업그레이드 요청, 새 템플릿 추가 요청, 즐겨찾기/내 티어표 관리까지 포함한 전체 기능 안내 허브로 확장함.
- 사용법 모달 제목과 단계 표기를 더 넓은 개념의 `기능 안내` 기준으로 정리하고, 실제 스크린샷이 없어도 설명만으로 핵심 기능을 순서대로 이해할 수 있게 단계 문구를 전면 보강함.
## 2026-04-01 v1.3.27 ## 2026-04-01 v1.3.27
- 오른쪽 사이드 하단에 책 아이콘 진입점을 추가하고, 중앙 대형 사용법 모달을 열어 좌측 기능 리스트와 우측 16:9 설명 영역, 좌우 이동, 하단 페이지네이션까지 포함한 기본 가이드 흐름을 붙임. - 오른쪽 사이드 하단에 책 아이콘 진입점을 추가하고, 중앙 대형 사용법 모달을 열어 좌측 기능 리스트와 우측 16:9 설명 영역, 좌우 이동, 하단 페이지네이션까지 포함한 기본 가이드 흐름을 붙임.
- 사용법 모달의 스크린샷 영역은 우선 16:9 플레이스홀더와 설명 텍스트만 배치해, 실제 이미지 자산은 나중에 채워 넣을 수 있게 구조를 먼저 준비함. - 사용법 모달의 스크린샷 영역은 우선 16:9 플레이스홀더와 설명 텍스트만 배치해, 실제 이미지 자산은 나중에 채워 넣을 수 있게 구조를 먼저 준비함.

View File

@@ -26,12 +26,14 @@ const searchQuery = ref('')
const searchPlaceholder = computed(() => (route.name === 'home' ? '게임 템플릿 검색' : '전체 티어표 검색')) const searchPlaceholder = computed(() => (route.name === 'home' ? '게임 템플릿 검색' : '전체 티어표 검색'))
const isCollapsedSearchOpen = ref(false) const isCollapsedSearchOpen = ref(false)
const isGuideModalOpen = ref(false) const isGuideModalOpen = ref(false)
const themeMode = ref('dark')
const guideStepIndex = ref(0) const guideStepIndex = ref(0)
const viewportWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1440) const viewportWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1440)
provide('rightRailOpen', rightRailOpen) provide('rightRailOpen', rightRailOpen)
provide('localRightRailTarget', '#local-right-rail-root') provide('localRightRailTarget', '#local-right-rail-root')
const isAdmin = computed(() => !!auth.user?.isAdmin) const authReady = computed(() => auth.hydrated)
const isAdmin = computed(() => authReady.value && !!auth.user?.isAdmin)
const isPreviewMode = computed(() => route.query.preview === '1') const isPreviewMode = computed(() => route.query.preview === '1')
const usesLocalRightRail = computed(() => ['editEditor', 'newEditor', 'admin'].includes(String(route.name || ''))) const usesLocalRightRail = computed(() => ['editEditor', 'newEditor', 'admin'].includes(String(route.name || '')))
const isRightRailOverlay = computed(() => viewportWidth.value <= 1200) const isRightRailOverlay = computed(() => viewportWidth.value <= 1200)
@@ -44,7 +46,10 @@ const accountName = computed(() => {
if (email) return email.split('@')[0] || email if (email) return email.split('@')[0] || email
return 'Guest' return 'Guest'
}) })
const accountEmail = computed(() => (auth.user?.email || '').trim() || '로그인 후 개인 메뉴를 사용할 수 있어요.') const accountEmail = computed(() => {
if (!authReady.value) return '계정 상태를 확인하고 있어요.'
return (auth.user?.email || '').trim() || '로그인 후 개인 메뉴를 사용할 수 있어요.'
})
const shellStyle = computed(() => ({ const shellStyle = computed(() => ({
'--left-rail-width': leftRailCollapsed.value ? '76px' : '248px', '--left-rail-width': leftRailCollapsed.value ? '76px' : '248px',
'--right-rail-width': !isRightRailOverlay.value && rightRailOpen.value ? '325px' : '0px', '--right-rail-width': !isRightRailOverlay.value && rightRailOpen.value ? '325px' : '0px',
@@ -56,41 +61,78 @@ const leftNavItems = computed(() => {
{ key: 'favorites', label: 'Favorites', path: '/favorites', iconSrc: iconFavorite, requiresAuth: true }, { key: 'favorites', label: 'Favorites', path: '/favorites', iconSrc: iconFavorite, requiresAuth: true },
{ key: 'profile', label: 'Settings', path: '/profile', iconSrc: iconSettings, requiresAuth: true }, { key: 'profile', label: 'Settings', path: '/profile', iconSrc: iconSettings, requiresAuth: true },
] ]
return items.filter((item) => !item.requiresAuth || auth.user) return items.filter((item) => !item.requiresAuth || (authReady.value && auth.user))
}) })
const showRightRailAction = computed(() => false) const showRightRailAction = computed(() => false)
const showSettingsGuideButton = computed(() => route.name === 'profile')
const guideSteps = [ const guideSteps = [
{ {
id: 'select-game', id: 'select-game',
title: '게임 또는 양식 선택', title: '게임 또는 양식 선택',
summary: '사용할 게임 템플릿을 고르거나 커스텀 티어표 시작합니다.', summary: '게임 템플릿을 고르거나 커스텀 티어표 만들기로 바로 시작합니다.',
description: '홈 화면에서 게임 템플릿을 고르거나 커스텀 티어표 만들기로 시작할 수 있어요. 게임 허브에서는 기존 공개 티어표도 살펴본 뒤 같은 흐름으로 새 보드를 만들 수 있습니다.', description:
'홈 화면에서는 게임 템플릿을 선택하거나 커스텀 티어표 만들기로 바로 새 보드를 열 수 있어요. 게임을 먼저 고르면 해당 게임의 공개 티어표도 같이 살펴볼 수 있어서, 완전히 처음 만드는지 기존 흐름을 참고할지 결정하기 쉽습니다.',
}, },
{ {
id: 'arrange-board', id: 'arrange-board',
title: '행과 열 구성', title: '행과 열 구성',
summary: '필요한 랭크와 열을 만들고 이름을 정리합니다.', summary: '랭크 행과 가로 열을 정리해 보드 구조를 먼저 잡습니다.',
description: '기본 행을 수정하거나 행·열을 추가해서 원하는 구조를 먼저 잡아보세요. 공격, 방어, 지원처럼 가로 열을 나누고 각 행 이름을 짧게 정리하면 실제 배치가 훨씬 빨라집니다.', description:
'기본 랭크를 그대로 써도 되고, 행 이름을 바꾸거나 행과 열을 추가해 공격·방어·지원처럼 더 세밀한 구조로 나눌 수도 있어요. 먼저 판을 정리한 뒤 배치를 시작하면 뒤에서 크게 손댈 일이 줄어듭니다.',
}, },
{ {
id: 'drop-items', id: 'drop-items',
title: '아이템 배치', title: '아이템 배치와 커스텀 추가',
summary: '프리셋 아이템과 커스텀 이미지를 드래그로 배치합니다.', summary: '프리셋 아이템과 직접 올린 이미지를 드래그로 배치합니다.',
description: '오른쪽 아이템 풀에서 이미지를 드래그해서 원하는 칸에 배치합니다. 직접 올린 커스텀 이미지도 같은 방식으로 다룰 수 있고, 이름 표시 옵션으로 결과 톤도 함께 맞출 수 있어요.', description:
'오른쪽 아이템 영역의 이미지를 원하는 칸으로 끌어다 놓으면 바로 배치됩니다. 게임 템플릿에 없는 이미지는 커스텀 이미지로 추가해 같이 쓸 수 있고, 이름 표시 옵션을 켜면 결과 이미지를 더 설명적으로 정리할 수 있어요.',
}, },
{ {
id: 'save-share', id: 'save-share',
title: '저장과 공유', title: '저장과 이미지 다운로드',
summary: '저장, 이미지 다운로드, 템플릿 요청까지 마무리합니다.', summary: '완성한 티어표를 내 목록에 저장하거나 PNG 이미지로 내려받습니다.',
description: '완성한 보드는 내 티어표로 저장하거나 PNG 이미지로 내려받을 수 있습니다. 공통 템플릿으로 쓰면 좋겠다면 템플릿 요청을 보내 관리자에게 추가를 제안할 수도 있어요.', description:
'보드 작업이 끝나면 저장해서 내 티어표 목록에 남길 수 있고, 이미지 다운로드로 한 장의 결과물로 바로 공유할 수도 있어요. 공개 여부도 함께 정할 수 있어서 개인 메모용과 공유용 흐름을 나눠 쓰기 좋습니다.',
},
{
id: 'copy-existing',
title: '다른 사람 티어표 복사',
summary: '공개된 티어표를 그대로 가져와 내 이름의 새 작업본으로 이어서 수정합니다.',
description:
'누군가 만든 티어표가 거의 마음에 드는데 일부만 바꾸고 싶다면, 복사 기능으로 현재 배치 상태를 그대로 가져와 새 티어표로 시작할 수 있어요. 복사본에는 원본을 참고했다는 정보가 함께 남아서 출처도 자연스럽게 구분됩니다.',
},
{
id: 'request-template-update',
title: '템플릿 업그레이드 요청',
summary: '현재 게임 템플릿에 공통 아이템을 추가해 달라고 관리자에게 요청합니다.',
description:
'직접 추가한 아이템 중 여러 사람이 함께 써도 좋을 것 같은 항목이 있다면 템플릿 업데이트 요청을 보낼 수 있어요. 요청 모달에서는 현재 티어표 제목과 설명을 기본값으로 가져오고, 필요하면 요청 제목과 설명을 더 다듬어 공통 템플릿에 왜 필요한지 설명할 수 있습니다.',
},
{
id: 'request-new-template',
title: '새 템플릿 추가 요청',
summary: '아직 없는 게임이나 새로운 양식을 관리자에게 제안합니다.',
description:
'원하는 게임 템플릿이 아직 없다면 새 템플릿 추가 요청으로 관리자에게 직접 제안할 수 있어요. 이때는 제목과 설명에 어떤 게임인지, 어떤 캐릭터나 항목이 기본으로 필요할지 적어두면 검토 속도가 훨씬 빨라집니다.',
},
{
id: 'manage-library',
title: '즐겨찾기와 내 티어표 관리',
summary: '마음에 드는 템플릿과 저장한 결과물을 나중에 다시 쉽게 찾습니다.',
description:
'게임 템플릿은 즐겨찾기로 상단에 고정해둘 수 있고, 저장한 보드는 내 티어표에서 다시 열어 이어서 수정할 수 있어요. 자주 보는 템플릿, 공개 티어표, 내가 만든 결과물을 각각 다른 화면에서 정리해두면 이후 작업이 훨씬 빨라집니다.',
}, },
] ]
const currentGuideStep = computed(() => guideSteps[guideStepIndex.value] || guideSteps[0]) const currentGuideStep = computed(() => guideSteps[guideStepIndex.value] || guideSteps[0])
const isGuidePrevDisabled = computed(() => guideStepIndex.value <= 0) const isGuidePrevDisabled = computed(() => guideStepIndex.value <= 0)
const isGuideNextDisabled = computed(() => guideStepIndex.value >= guideSteps.length - 1) const isGuideNextDisabled = computed(() => guideStepIndex.value >= guideSteps.length - 1)
const isLightTheme = computed(() => themeMode.value === 'light')
const themeToggleLabel = computed(() => (isLightTheme.value ? '다크 모드' : '라이트 모드'))
const showSettingsThemePanel = computed(() => route.name === 'profile')
const showGameHubViewToggle = computed(() => route.name === 'gameHub') const showGameHubViewToggle = computed(() => route.name === 'gameHub')
const gameHubViewMode = computed(() => (route.query.view === 'list' ? 'list' : 'grid')) const gameHubViewMode = computed(() => (route.query.view === 'list' ? 'list' : 'grid'))
const leftBottomPrimaryAction = computed(() => { const leftBottomPrimaryAction = computed(() => {
if (!authReady.value) return null
if (route.name === 'home' && auth.user) { if (route.name === 'home' && auth.user) {
return { label: '커스텀 티어표 만들기', to: '/editor/freeform/new' } return { label: '커스텀 티어표 만들기', to: '/editor/freeform/new' }
} }
@@ -202,7 +244,22 @@ function syncViewportWidth() {
viewportWidth.value = window.innerWidth viewportWidth.value = window.innerWidth
} }
function applyTheme(mode) {
themeMode.value = mode === 'light' ? 'light' : 'dark'
if (typeof document !== 'undefined') document.documentElement.dataset.theme = themeMode.value
if (typeof window !== 'undefined') window.localStorage.setItem('tier-maker:theme', themeMode.value)
}
function toggleTheme() {
applyTheme(isLightTheme.value ? 'dark' : 'light')
}
onMounted(async () => { onMounted(async () => {
if (typeof window !== 'undefined') {
const savedTheme = window.localStorage.getItem('tier-maker:theme')
if (savedTheme === 'light' || savedTheme === 'dark') applyTheme(savedTheme)
else applyTheme(window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark')
}
await auth.refresh() await auth.refresh()
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
syncViewportWidth() syncViewportWidth()
@@ -369,7 +426,7 @@ function submitGlobalSearch() {
<div class="leftRail__body"> <div class="leftRail__body">
<div class="leftRail__content"> <div class="leftRail__content">
<div v-if="auth.user" class="appUserCard"> <div v-if="authReady && auth.user" class="appUserCard">
<div class="appUserCard__button"> <div class="appUserCard__button">
<img v-if="avatarUrl" :src="avatarUrl" class="appUserCard__avatar" alt="avatar" /> <img v-if="avatarUrl" :src="avatarUrl" class="appUserCard__avatar" alt="avatar" />
<div v-else class="appUserCard__avatar appUserCard__avatar--fallback">{{ accountName[0]?.toUpperCase() || 'U' }}</div> <div v-else class="appUserCard__avatar appUserCard__avatar--fallback">{{ accountName[0]?.toUpperCase() || 'U' }}</div>
@@ -410,8 +467,12 @@ function submitGlobalSearch() {
</div> </div>
<div class="leftRail__bottom"> <div class="leftRail__bottom">
<RouterLink v-if="leftBottomPrimaryAction" :to="leftBottomPrimaryAction.to" class="adminButton">{{ leftBottomPrimaryAction.label }}</RouterLink> <RouterLink v-if="leftBottomPrimaryAction" :to="leftBottomPrimaryAction.to" class="adminButton">{{ leftBottomPrimaryAction.label }}</RouterLink>
<RouterLink v-if="isAdmin" to="/admin" class="adminButton">관리자 메뉴</RouterLink> <button v-if="showSettingsGuideButton" class="adminButton adminButton--icon" type="button" @click="openGuideModal()">
<RouterLink v-else-if="!auth.user" to="/login" class="adminButton">로그인</RouterLink> <SvgIcon :src="iconMenuBook" :size="18" class="adminButton__icon" />
<span>가이드 보기</span>
</button>
<RouterLink v-if="authReady && isAdmin" to="/admin" class="adminButton">관리자 메뉴</RouterLink>
<RouterLink v-else-if="authReady && !auth.user" to="/login" class="adminButton">로그인</RouterLink>
</div> </div>
</div> </div>
</aside> </aside>
@@ -421,7 +482,15 @@ function submitGlobalSearch() {
<header class="workspaceHead railHeader"> <header class="workspaceHead railHeader">
<div class="workspaceHead__brand" @click="$router.push('/')"> <div class="workspaceHead__brand" @click="$router.push('/')">
<span class="workspaceHead__brandTitle">Tier Maker</span> <span class="workspaceHead__brandTitle">Tier Maker</span>
<span class="workspaceHead__brandSub">by zenn</span> <a
class="workspaceHead__brandSub"
href="https://zenn.town/@murabito"
target="_blank"
rel="noreferrer"
@click.stop
>
by zenn
</a>
</div> </div>
<div class="workspaceHead__actions"> <div class="workspaceHead__actions">
<div v-if="showGameHubViewToggle" class="viewToggle" role="group" aria-label="티어표 보기 방식"> <div v-if="showGameHubViewToggle" class="viewToggle" role="group" aria-label="티어표 보기 방식">
@@ -452,11 +521,11 @@ function submitGlobalSearch() {
</form> </form>
</div> </div>
<div v-if="isGuideModalOpen" class="guideModal" role="dialog" aria-modal="true" aria-label="티어 메이커 사용법" @click.self="closeGuideModal"> <div v-if="isGuideModalOpen" class="guideModal" role="dialog" aria-modal="true" aria-label="티어 메이커 기능 안내" @click.self="closeGuideModal">
<div class="guideModal__dialog"> <div class="guideModal__dialog">
<div class="guideModal__sidebar"> <div class="guideModal__sidebar">
<div class="guideModal__eyebrow">Guide</div> <div class="guideModal__eyebrow">Guide</div>
<div class="guideModal__title">티어 제작 흐름</div> <div class="guideModal__title">티어 메이커 기능 안내</div>
<div class="guideModal__list"> <div class="guideModal__list">
<button <button
v-for="(step, index) in guideSteps" v-for="(step, index) in guideSteps"
@@ -484,7 +553,7 @@ function submitGlobalSearch() {
</div> </div>
</div> </div>
<div class="guideModal__text"> <div class="guideModal__text">
<div class="guideModal__stepLabel">STEP {{ guideStepIndex + 1 }}</div> <div class="guideModal__stepLabel">GUIDE {{ guideStepIndex + 1 }}</div>
<div class="guideModal__stepTitle">{{ currentGuideStep.title }}</div> <div class="guideModal__stepTitle">{{ currentGuideStep.title }}</div>
<div class="guideModal__stepSummary">{{ currentGuideStep.summary }}</div> <div class="guideModal__stepSummary">{{ currentGuideStep.summary }}</div>
<p class="guideModal__stepDescription">{{ currentGuideStep.description }}</p> <p class="guideModal__stepDescription">{{ currentGuideStep.description }}</p>
@@ -524,7 +593,17 @@ function submitGlobalSearch() {
<div class="rightRail__content"> <div class="rightRail__content">
<div v-if="usesLocalRightRail" id="local-right-rail-root" class="localRightRailRoot"></div> <div v-if="usesLocalRightRail" id="local-right-rail-root" class="localRightRailRoot"></div>
<template v-else> <template v-else>
<RightRailAd /> <section v-if="showSettingsThemePanel" class="settingsThemePanel">
<div class="settingsThemePanel__eyebrow">Appearance</div>
<div class="settingsThemePanel__title">테마 설정</div>
<div class="settingsThemePanel__desc">밝은 톤과 어두운 원하는 작업 환경으로 전환할 있어요.</div>
<label class="toggleSwitch settingsThemePanel__toggle">
<input :checked="isLightTheme" type="checkbox" @change="toggleTheme" />
<span class="toggleSwitch__label">{{ isLightTheme ? '라이트 모드' : '다크 모드' }}</span>
<span class="toggleSwitch__track"><span class="toggleSwitch__thumb"></span></span>
</label>
</section>
<RightRailAd v-else />
</template> </template>
</div> </div>
<div class="rightRail__bottom"> <div class="rightRail__bottom">
@@ -535,9 +614,6 @@ function submitGlobalSearch() {
</button> </button>
</section> </section>
</template> </template>
<button class="guideDockButton" type="button" aria-label="사용법 열기" @click="openGuideModal()">
<SvgIcon :src="iconMenuBook" :size="22" />
</button>
</div> </div>
</div> </div>
</aside> </aside>
@@ -560,8 +636,8 @@ function submitGlobalSearch() {
min-height: 100dvh; min-height: 100dvh;
display: grid; display: grid;
grid-template-columns: var(--left-rail-width, 248px) minmax(0, 1fr) var(--right-rail-width, 325px); grid-template-columns: var(--left-rail-width, 248px) minmax(0, 1fr) var(--right-rail-width, 325px);
background: rgba(14, 14, 14, 0.96); background: var(--theme-shell-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
transition: grid-template-columns 220ms ease; transition: grid-template-columns 220ms ease;
} }
@@ -572,8 +648,8 @@ function submitGlobalSearch() {
.leftRail, .leftRail,
.rightRail { .rightRail {
min-height: 100dvh; min-height: 100dvh;
border-right: 1px solid rgba(255, 255, 255, 0.08); border-right: 1px solid var(--theme-border);
background: rgba(14, 14, 14, 0.92); background: var(--theme-rail-bg);
box-sizing: border-box; box-sizing: border-box;
min-width: 0; min-width: 0;
display: flex; display: flex;
@@ -583,7 +659,7 @@ function submitGlobalSearch() {
.rightRail { .rightRail {
border-right: 0; border-right: 0;
border-left: 1px solid rgba(255, 255, 255, 0.08); border-left: 1px solid var(--theme-border);
transition: transition:
opacity 220ms ease, opacity 220ms ease,
transform 220ms ease, transform 220ms ease,
@@ -607,7 +683,7 @@ function submitGlobalSearch() {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 12px; padding: 0 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08); border-bottom: 1px solid var(--theme-border);
box-sizing: border-box; box-sizing: border-box;
} }
@@ -666,9 +742,9 @@ function submitGlobalSearch() {
height: 28px; height: 28px;
padding: 0 10px; padding: 0 10px;
border-radius: 8px; border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.72); color: var(--theme-text-soft);
cursor: pointer; cursor: pointer;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -695,7 +771,7 @@ function submitGlobalSearch() {
width: 24px; width: 24px;
height: 24px; height: 24px;
display: block; display: block;
filter: brightness(0) saturate(100%) invert(94%) sepia(6%) saturate(207%) hue-rotate(186deg) brightness(96%) contrast(92%); filter: var(--theme-icon-filter);
} }
.ghostIcon--iconOnly { .ghostIcon--iconOnly {
@@ -736,13 +812,13 @@ function submitGlobalSearch() {
object-fit: cover; object-fit: cover;
flex: 0 0 auto; flex: 0 0 auto;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid rgba(255, 255, 255, 0.14);
background: rgba(255, 255, 255, 0.08); background: var(--theme-surface-soft-3);
} }
.appUserCard__avatar--fallback { .appUserCard__avatar--fallback {
display: grid; display: grid;
place-items: center; place-items: center;
background: rgba(255, 255, 255, 0.12); background: var(--theme-surface-soft-3);
font-weight: 900; font-weight: 900;
} }
@@ -762,7 +838,7 @@ function submitGlobalSearch() {
.appUserCard__email { .appUserCard__email {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-muted);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -775,9 +851,9 @@ function submitGlobalSearch() {
gap: 10px; gap: 10px;
padding: 11px 12px; padding: 11px 12px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-soft);
margin-bottom: 14px; margin-bottom: 14px;
box-sizing: border-box; box-sizing: border-box;
transition: padding 220ms ease, justify-content 220ms ease; transition: padding 220ms ease, justify-content 220ms ease;
@@ -789,7 +865,7 @@ function submitGlobalSearch() {
max-width: 100%; max-width: 100%;
border: 0; border: 0;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
outline: none; outline: none;
font: inherit; font: inherit;
overflow: hidden; overflow: hidden;
@@ -797,7 +873,7 @@ function submitGlobalSearch() {
} }
.searchStub__input::placeholder { .searchStub__input::placeholder {
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
} }
.searchStub__iconButton { .searchStub__iconButton {
@@ -830,7 +906,7 @@ function submitGlobalSearch() {
gap: 12px; gap: 12px;
padding: 11px 12px; padding: 11px 12px;
border-radius: 14px; border-radius: 14px;
color: rgba(255, 255, 255, 0.76); color: var(--theme-text-muted);
text-decoration: none; text-decoration: none;
transition: background 180ms ease, color 180ms ease, transform 180ms ease; transition: background 180ms ease, color 180ms ease, transform 180ms ease;
} }
@@ -845,8 +921,8 @@ function submitGlobalSearch() {
.leftNav__item--active, .leftNav__item--active,
.leftNav__item.router-link-active { .leftNav__item.router-link-active {
background: rgba(255, 255, 255, 0.1); background: var(--theme-surface-soft-3);
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
} }
.leftNav__glyph { .leftNav__glyph {
@@ -928,23 +1004,32 @@ function submitGlobalSearch() {
display: inline-flex; display: inline-flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 8px;
padding: 12px 14px; padding: 12px 14px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.05); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
text-decoration: none; text-decoration: none;
box-sizing: border-box; box-sizing: border-box;
font-weight: 800; font-weight: 800;
} }
.adminButton--icon {
text-align: center;
}
.adminButton__icon {
flex: 0 0 auto;
}
.appMain { .appMain {
min-width: 0; min-width: 0;
min-height: 0; min-height: 0;
box-sizing: border-box; box-sizing: border-box;
background: rgba(18, 18, 18, 0.98); background: var(--theme-main-bg);
border-left: 1px solid rgba(255, 255, 255, 0.08); border-left: 1px solid var(--theme-border);
border-right: 1px solid rgba(255, 255, 255, 0.08); border-right: 1px solid var(--theme-border);
} }
.appMain--preview { .appMain--preview {
@@ -980,12 +1065,22 @@ function submitGlobalSearch() {
font-size: 28px; font-size: 28px;
font-weight: 900; font-weight: 900;
letter-spacing: -0.05em; letter-spacing: -0.05em;
background-image: linear-gradient(90deg, #ff75c3 0%, #ffa647 20%, #ffe83f 40%, #9fff5b 60%, #70e2ff 80%, #cd93ff 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
} }
.workspaceHead__brandSub { .workspaceHead__brandSub {
font-size: 13px; font-size: 13px;
font-weight: 700; font-weight: 700;
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
text-decoration: none;
transition: color 180ms ease, opacity 180ms ease;
}
.workspaceHead__brandSub:hover {
color: var(--theme-text);
} }
.workspaceHead__actions { .workspaceHead__actions {
@@ -1001,7 +1096,7 @@ function submitGlobalSearch() {
gap: 6px; gap: 6px;
padding: 4px; padding: 4px;
border-radius: 14px; border-radius: 14px;
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.viewToggle .ghostIcon--iconOnly { .viewToggle .ghostIcon--iconOnly {
@@ -1012,7 +1107,7 @@ function submitGlobalSearch() {
} }
.ghostIcon--active { .ghostIcon--active {
background: rgba(255, 255, 255, 0.08); background: var(--theme-surface-soft-3);
} }
.workspaceBody { .workspaceBody {
@@ -1020,7 +1115,7 @@ function submitGlobalSearch() {
padding: 18px 18px 32px; padding: 18px 18px 32px;
border: 0; border: 0;
border-radius: 0; border-radius: 0;
background: rgba(24, 24, 24, 0.92); background: var(--theme-workspace-bg);
box-shadow: none; box-shadow: none;
margin: 0; margin: 0;
} }
@@ -1030,7 +1125,7 @@ function submitGlobalSearch() {
padding: 18px 18px 32px; padding: 18px 18px 32px;
border: 0; border: 0;
border-radius: 0; border-radius: 0;
background: rgba(24, 24, 24, 0.92); background: var(--theme-workspace-bg);
box-shadow: none; box-shadow: none;
margin: 0; margin: 0;
} }
@@ -1052,23 +1147,96 @@ function submitGlobalSearch() {
padding-top: 12px; padding-top: 12px;
} }
.guideDockButton { .settingsThemePanel {
width: 42px; display: grid;
height: 42px; gap: 10px;
border-radius: 14px; padding: 18px;
border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 22px;
background: rgba(255, 255, 255, 0.04); border: 1px solid var(--theme-border);
color: rgba(255, 255, 255, 0.78); background: var(--theme-pill-bg);
}
.settingsThemePanel__eyebrow {
font-size: 11px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--theme-text-soft);
}
.settingsThemePanel__title {
font-size: 22px;
font-weight: 800;
color: var(--theme-text-strong);
}
.settingsThemePanel__desc {
color: var(--theme-text-muted);
line-height: 1.6;
}
.settingsThemePanel__toggle {
margin-top: 4px;
}
.toggleSwitch {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: space-between;
gap: 12px;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid var(--theme-border-strong);
background: var(--theme-surface-soft);
cursor: pointer; cursor: pointer;
user-select: none;
}
.toggleSwitch input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.toggleSwitch__track {
position: relative;
width: 42px;
height: 24px;
border-radius: 999px;
background: var(--theme-surface-soft-3);
border: 1px solid var(--theme-border-strong);
transition: background 180ms ease, border-color 180ms ease;
flex: 0 0 auto; flex: 0 0 auto;
} }
.guideDockButton:hover { .toggleSwitch__thumb {
background: rgba(255, 255, 255, 0.08); position: absolute;
color: rgba(255, 255, 255, 0.96); top: 2px;
left: 2px;
width: 18px;
height: 18px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.94);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.24);
transition: transform 180ms ease;
}
:root[data-theme='light'] .toggleSwitch__thumb {
background: #fff;
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.16);
}
.toggleSwitch__label {
font-weight: 800;
color: var(--theme-text);
}
.toggleSwitch input:checked ~ .toggleSwitch__track {
background: rgba(96, 165, 250, 0.34);
border-color: rgba(96, 165, 250, 0.42);
}
.toggleSwitch input:checked ~ .toggleSwitch__track .toggleSwitch__thumb {
transform: translateX(18px);
} }
.rightRailAction__button { .rightRailAction__button {
@@ -1076,8 +1244,8 @@ function submitGlobalSearch() {
padding: 12px 14px; padding: 12px 14px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(77, 127, 233, 0.96); border: 1px solid rgba(77, 127, 233, 0.96);
background: rgba(77, 127, 233, 0.88); background: var(--theme-accent-bg);
color: #fff; color: var(--theme-accent-text);
font-weight: 800; font-weight: 800;
cursor: pointer; cursor: pointer;
} }
@@ -1105,7 +1273,7 @@ function submitGlobalSearch() {
grid-template-columns: 260px minmax(0, 1fr); grid-template-columns: 260px minmax(0, 1fr);
border-radius: 28px; border-radius: 28px;
overflow: hidden; overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border-strong);
background: linear-gradient(180deg, rgba(34, 34, 34, 0.98), rgba(18, 18, 18, 0.98)); background: linear-gradient(180deg, rgba(34, 34, 34, 0.98), rgba(18, 18, 18, 0.98));
box-shadow: 0 28px 90px rgba(0, 0, 0, 0.42); box-shadow: 0 28px 90px rgba(0, 0, 0, 0.42);
} }
@@ -1115,15 +1283,15 @@ function submitGlobalSearch() {
align-content: start; align-content: start;
gap: 18px; gap: 18px;
padding: 28px 22px; padding: 28px 22px;
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
border-right: 1px solid rgba(255, 255, 255, 0.08); border-right: 1px solid var(--theme-border);
} }
.guideModal__eyebrow { .guideModal__eyebrow {
font-size: 11px; font-size: 11px;
letter-spacing: 0.14em; letter-spacing: 0.14em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.4); color: var(--theme-text-faint);
} }
.guideModal__title { .guideModal__title {
@@ -1145,9 +1313,9 @@ function submitGlobalSearch() {
align-items: center; align-items: center;
padding: 12px 14px; padding: 12px 14px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.02); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.8); color: var(--theme-text-muted);
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
} }
@@ -1155,13 +1323,13 @@ function submitGlobalSearch() {
.guideModal__listItem--active { .guideModal__listItem--active {
border-color: rgba(77, 127, 233, 0.5); border-color: rgba(77, 127, 233, 0.5);
background: rgba(77, 127, 233, 0.14); background: rgba(77, 127, 233, 0.14);
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
} }
.guideModal__listIndex { .guideModal__listIndex {
font-size: 12px; font-size: 12px;
font-weight: 900; font-weight: 900;
color: rgba(255, 255, 255, 0.54); color: var(--theme-text-faint);
} }
.guideModal__listLabel { .guideModal__listLabel {
@@ -1181,7 +1349,7 @@ function submitGlobalSearch() {
justify-self: end; justify-self: end;
border: 0; border: 0;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-muted);
cursor: pointer; cursor: pointer;
font-size: 13px; font-size: 13px;
} }
@@ -1209,7 +1377,7 @@ function submitGlobalSearch() {
width: 100%; width: 100%;
aspect-ratio: 16 / 9; aspect-ratio: 16 / 9;
border-radius: 24px; border-radius: 24px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: radial-gradient(circle at top, rgba(77, 127, 233, 0.18), rgba(255, 255, 255, 0.02) 52%), rgba(255, 255, 255, 0.03); background: radial-gradient(circle at top, rgba(77, 127, 233, 0.18), rgba(255, 255, 255, 0.02) 52%), rgba(255, 255, 255, 0.03);
display: grid; display: grid;
align-content: center; align-content: center;
@@ -1232,7 +1400,7 @@ function submitGlobalSearch() {
.guideModal__mediaHint { .guideModal__mediaHint {
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.48); color: var(--theme-text-faint);
} }
.guideModal__text { .guideModal__text {
@@ -1244,7 +1412,7 @@ function submitGlobalSearch() {
font-size: 11px; font-size: 11px;
letter-spacing: 0.14em; letter-spacing: 0.14em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
} }
.guideModal__stepTitle { .guideModal__stepTitle {
@@ -1256,14 +1424,14 @@ function submitGlobalSearch() {
.guideModal__stepSummary { .guideModal__stepSummary {
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
color: rgba(255, 255, 255, 0.86); color: var(--theme-text);
} }
.guideModal__stepDescription { .guideModal__stepDescription {
margin: 0; margin: 0;
max-width: 720px; max-width: 720px;
line-height: 1.7; line-height: 1.7;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-soft);
} }
.guideModal__footer { .guideModal__footer {
@@ -1284,7 +1452,7 @@ function submitGlobalSearch() {
height: 10px; height: 10px;
border-radius: 999px; border-radius: 999px;
border: 0; border: 0;
background: rgba(255, 255, 255, 0.18); background: var(--theme-surface-soft-3);
cursor: pointer; cursor: pointer;
} }
@@ -1297,8 +1465,8 @@ function submitGlobalSearch() {
padding: 12px 18px; padding: 12px 18px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(77, 127, 233, 0.96); border: 1px solid rgba(77, 127, 233, 0.96);
background: rgba(77, 127, 233, 0.88); background: var(--theme-accent-bg);
color: #fff; color: var(--theme-accent-text);
font-weight: 800; font-weight: 800;
cursor: pointer; cursor: pointer;
} }
@@ -1307,9 +1475,9 @@ function submitGlobalSearch() {
width: 52px; width: 52px;
height: 52px; height: 52px;
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
font-size: 28px; font-size: 28px;
line-height: 1; line-height: 1;
cursor: pointer; cursor: pointer;
@@ -1328,7 +1496,7 @@ function submitGlobalSearch() {
justify-content: center; justify-content: center;
align-items: flex-start; align-items: flex-start;
padding: 88px 20px 20px; padding: 88px 20px 20px;
background: rgba(0, 0, 0, 0.44); background: color-mix(in srgb, var(--theme-body-bg) 72%, transparent);
backdrop-filter: blur(6px); backdrop-filter: blur(6px);
} }
@@ -1339,8 +1507,8 @@ function submitGlobalSearch() {
gap: 14px; gap: 14px;
padding: 18px 22px; padding: 18px 22px;
border-radius: 24px; border-radius: 24px;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border-strong);
background: rgba(26, 26, 26, 0.96); background: var(--theme-main-bg);
box-shadow: 0 28px 60px rgba(0, 0, 0, 0.34); box-shadow: 0 28px 60px rgba(0, 0, 0, 0.34);
} }
@@ -1357,7 +1525,7 @@ function submitGlobalSearch() {
width: 28px; width: 28px;
height: 28px; height: 28px;
display: block; display: block;
filter: brightness(0) saturate(100%) invert(94%) sepia(6%) saturate(207%) hue-rotate(186deg) brightness(96%) contrast(92%); filter: var(--theme-icon-filter);
} }
.collapsedSearchBar__input { .collapsedSearchBar__input {
@@ -1365,14 +1533,14 @@ function submitGlobalSearch() {
flex: 1; flex: 1;
border: 0; border: 0;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
font-size: 18px; font-size: 18px;
font-weight: 700; font-weight: 700;
outline: none; outline: none;
} }
.collapsedSearchBar__input::placeholder { .collapsedSearchBar__input::placeholder {
color: rgba(255, 255, 255, 0.46); color: var(--theme-text-faint);
} }
.localRightRailRoot { .localRightRailRoot {
@@ -1403,8 +1571,8 @@ function submitGlobalSearch() {
justify-content: space-between; justify-content: space-between;
padding: 12px 14px; padding: 12px 14px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
background: rgba(11, 18, 32, 0.94); background: color-mix(in srgb, var(--theme-main-bg) 94%, transparent);
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.28); box-shadow: 0 14px 30px rgba(0, 0, 0, 0.28);
opacity: 1; opacity: 1;
@@ -1437,13 +1605,13 @@ function submitGlobalSearch() {
.toast__count { .toast__count {
margin-top: 6px; margin-top: 6px;
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-muted);
} }
.toast__close { .toast__close {
border: 0; border: 0;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.68); color: var(--theme-text-muted);
cursor: pointer; cursor: pointer;
font-size: 12px; font-size: 12px;
} }
@@ -1456,7 +1624,7 @@ function submitGlobalSearch() {
.guideModal__sidebar { .guideModal__sidebar {
border-right: 0; border-right: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.08); border-bottom: 1px solid var(--theme-border);
} }
.guideModal__content { .guideModal__content {
@@ -1483,8 +1651,8 @@ function submitGlobalSearch() {
width: min(360px, calc(100vw - 20px)); width: min(360px, calc(100vw - 20px));
height: 100dvh; height: 100dvh;
z-index: 30; z-index: 30;
border-left: 1px solid rgba(255, 255, 255, 0.08); border-left: 1px solid var(--theme-border);
background: rgba(14, 14, 14, 0.96); background: var(--theme-shell-bg);
box-shadow: -18px 0 36px rgba(0, 0, 0, 0.34); box-shadow: -18px 0 36px rgba(0, 0, 0, 0.34);
} }
@@ -1545,7 +1713,7 @@ function submitGlobalSearch() {
min-height: auto; min-height: auto;
height: auto; height: auto;
border-right: 0; border-right: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.08); border-bottom: 1px solid var(--theme-border);
} }
.leftRail__top { .leftRail__top {

View File

@@ -5,30 +5,40 @@ export const useAuthStore = defineStore('auth', {
state: () => ({ state: () => ({
user: null, user: null,
status: 'idle', status: 'idle',
hydrated: false,
}), }),
actions: { actions: {
async refresh() { async refresh() {
if (this.status === 'loading') return this.user
this.status = 'loading' this.status = 'loading'
try { try {
const data = await api.me() const data = await api.me()
this.user = data.user this.user = data.user
return this.user
} catch (error) {
this.user = null
return null
} finally { } finally {
this.status = 'idle' this.status = 'idle'
this.hydrated = true
} }
}, },
async signup(email, password) { async signup(email, password) {
const user = await api.signup({ email, password }) const user = await api.signup({ email, password })
this.user = user this.user = user
this.hydrated = true
return user return user
}, },
async login(email, password) { async login(email, password) {
const user = await api.login({ email, password }) const user = await api.login({ email, password })
this.user = user this.user = user
this.hydrated = true
return user return user
}, },
async logout() { async logout() {
await api.logout() await api.logout()
this.user = null this.user = null
this.hydrated = true
}, },
}, },
}) })

View File

@@ -2,12 +2,69 @@
font-family: 'Pretendard', 'Inter', 'Segoe UI', sans-serif; font-family: 'Pretendard', 'Inter', 'Segoe UI', sans-serif;
line-height: 1.5; line-height: 1.5;
font-weight: 400; font-weight: 400;
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
background: #121212; background: var(--theme-body-bg);
font-synthesis: none; font-synthesis: none;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
--theme-body-bg: #121212;
--theme-shell-bg: rgba(14, 14, 14, 0.96);
--theme-rail-bg: rgba(14, 14, 14, 0.92);
--theme-main-bg: rgba(18, 18, 18, 0.98);
--theme-workspace-bg: rgba(24, 24, 24, 0.92);
--theme-card-bg: rgba(62, 62, 62, 0.82);
--theme-card-bg-hover: rgba(70, 70, 70, 0.96);
--theme-card-border: rgba(255, 255, 255, 0.16);
--theme-card-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
--theme-surface-soft: rgba(255, 255, 255, 0.05);
--theme-surface-soft-2: rgba(255, 255, 255, 0.06);
--theme-surface-soft-3: rgba(255, 255, 255, 0.08);
--theme-pill-bg: rgba(255, 255, 255, 0.03);
--theme-border: rgba(255, 255, 255, 0.08);
--theme-border-strong: rgba(255, 255, 255, 0.12);
--theme-text: rgba(255, 255, 255, 0.92);
--theme-text-strong: rgba(255, 255, 255, 0.98);
--theme-text-muted: rgba(255, 255, 255, 0.74);
--theme-text-soft: rgba(255, 255, 255, 0.62);
--theme-text-faint: rgba(255, 255, 255, 0.4);
--theme-thumb-fallback-bg: #555;
--theme-select-arrow: rgba(255, 255, 255, 0.68);
--theme-danger-bg: rgba(239, 68, 68, 0.1);
--theme-danger-border: rgba(239, 68, 68, 0.18);
--theme-accent-bg: rgba(76, 133, 245, 0.92);
--theme-accent-text: #fff;
--theme-icon-filter: brightness(0) saturate(100%) invert(94%) sepia(6%) saturate(207%) hue-rotate(186deg) brightness(96%) contrast(92%);
}
:root[data-theme='light'] {
--theme-body-bg: #edf1f7;
--theme-shell-bg: rgba(244, 247, 252, 0.98);
--theme-rail-bg: rgba(248, 250, 253, 0.96);
--theme-main-bg: rgba(241, 244, 249, 0.98);
--theme-workspace-bg: rgba(250, 252, 255, 0.95);
--theme-card-bg: rgba(255, 255, 255, 0.98);
--theme-card-bg-hover: rgba(245, 248, 255, 0.98);
--theme-card-border: rgba(26, 32, 44, 0.1);
--theme-card-shadow: 0 18px 34px rgba(31, 41, 55, 0.08);
--theme-surface-soft: rgba(15, 23, 42, 0.05);
--theme-surface-soft-2: rgba(15, 23, 42, 0.07);
--theme-surface-soft-3: rgba(15, 23, 42, 0.1);
--theme-pill-bg: rgba(15, 23, 42, 0.04);
--theme-border: rgba(15, 23, 42, 0.1);
--theme-border-strong: rgba(15, 23, 42, 0.14);
--theme-text: rgba(20, 27, 40, 0.9);
--theme-text-strong: rgba(10, 15, 28, 0.98);
--theme-text-muted: rgba(55, 65, 81, 0.74);
--theme-text-soft: rgba(75, 85, 99, 0.64);
--theme-text-faint: rgba(100, 116, 139, 0.82);
--theme-thumb-fallback-bg: #d8dde8;
--theme-select-arrow: rgba(55, 65, 81, 0.72);
--theme-danger-bg: rgba(239, 68, 68, 0.1);
--theme-danger-border: rgba(239, 68, 68, 0.22);
--theme-accent-bg: rgba(64, 110, 226, 0.94);
--theme-accent-text: #fff;
--theme-icon-filter: brightness(0) saturate(100%) invert(14%) sepia(14%) saturate(652%) hue-rotate(182deg) brightness(95%) contrast(91%);
} }
* { * {
@@ -22,7 +79,9 @@ body,
body { body {
margin: 0; margin: 0;
background: #121212; background: var(--theme-body-bg);
color: var(--theme-text);
transition: background 220ms ease, color 220ms ease;
} }
button, button,
@@ -43,7 +102,7 @@ a {
input, input,
select, select,
textarea { textarea {
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
} }
select { select {
@@ -51,8 +110,8 @@ select {
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
background-image: background-image:
linear-gradient(45deg, transparent 50%, rgba(255, 255, 255, 0.72) 50%), linear-gradient(45deg, transparent 50%, var(--theme-select-arrow) 50%),
linear-gradient(135deg, rgba(255, 255, 255, 0.72) 50%, transparent 50%); linear-gradient(135deg, var(--theme-select-arrow) 50%, transparent 50%);
background-position: background-position:
calc(100% - 20px) calc(50% - 2px), calc(100% - 20px) calc(50% - 2px),
calc(100% - 14px) calc(50% - 2px); calc(100% - 14px) calc(50% - 2px);
@@ -99,19 +158,19 @@ p {
font-size: 11px; font-size: 11px;
letter-spacing: 0.12em; letter-spacing: 0.12em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
} }
.pageHead__title { .pageHead__title {
font-size: 32px; font-size: 32px;
line-height: 1.05; line-height: 1.05;
letter-spacing: -0.04em; letter-spacing: -0.04em;
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
} }
.pageHead__desc { .pageHead__desc {
max-width: 720px; max-width: 720px;
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
} }
.pageHead__aside { .pageHead__aside {

View File

@@ -2267,17 +2267,17 @@ async function saveFeaturedOrder() {
gap: 10px; gap: 10px;
padding: 22px 24px; padding: 22px 24px;
border-radius: 24px; border-radius: 24px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: background:
linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02)), linear-gradient(180deg, var(--theme-surface-soft-2), var(--theme-pill-bg)),
rgba(255, 255, 255, 0.02); var(--theme-pill-bg);
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.22); box-shadow: 0 20px 50px rgba(0, 0, 0, 0.22);
} }
.adminHero__eyebrow { .adminHero__eyebrow {
font-size: 11px; font-size: 11px;
letter-spacing: 0.12em; letter-spacing: 0.12em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-faint);
} }
.adminHero__title { .adminHero__title {
margin: 0; margin: 0;
@@ -2288,7 +2288,7 @@ async function saveFeaturedOrder() {
} }
.adminHero__desc { .adminHero__desc {
margin: 0; margin: 0;
color: rgba(255, 255, 255, 0.66); color: var(--theme-text-muted);
line-height: 1.6; line-height: 1.6;
} }
.adminHero__stats { .adminHero__stats {
@@ -2302,14 +2302,14 @@ async function saveFeaturedOrder() {
gap: 6px; gap: 6px;
padding: 14px 16px; padding: 14px 16px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(7, 7, 7, 0.18); background: var(--theme-pill-bg);
} }
.adminHeroStat__label { .adminHeroStat__label {
font-size: 11px; font-size: 11px;
letter-spacing: 0.08em; letter-spacing: 0.08em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.46); color: var(--theme-text-faint);
} }
.adminHeroStat__value { .adminHeroStat__value {
font-size: 22px; font-size: 22px;
@@ -2326,10 +2326,10 @@ async function saveFeaturedOrder() {
gap: 12px; gap: 12px;
padding: 16px; padding: 16px;
border-radius: 22px; border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: background:
linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.015)), linear-gradient(180deg, var(--theme-surface-soft), var(--theme-pill-bg)),
rgba(13, 13, 13, 0.94); color-mix(in srgb, var(--theme-rail-bg) 98%, transparent);
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.18); box-shadow: 0 18px 40px rgba(0, 0, 0, 0.18);
} }
@@ -2344,10 +2344,10 @@ async function saveFeaturedOrder() {
} }
.imageJobRow { .imageJobRow {
border: 1px solid var(--line); border: 1px solid var(--theme-border);
border-radius: 14px; border-radius: 14px;
padding: 10px 12px; padding: 10px 12px;
background: rgba(255, 255, 255, 0.02); background: var(--theme-pill-bg);
display: grid; display: grid;
gap: 4px; gap: 4px;
} }
@@ -2361,14 +2361,14 @@ async function saveFeaturedOrder() {
} }
.imageJobRow__status { .imageJobRow__status {
color: var(--text-muted); color: var(--theme-text-soft);
text-transform: capitalize; text-transform: capitalize;
} }
.adminSidebar__label { .adminSidebar__label {
font-size: 11px; font-size: 11px;
letter-spacing: 0.12em; letter-spacing: 0.12em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-faint);
} }
.adminSidebar__tabs, .adminSidebar__tabs,
.adminSidebar__group, .adminSidebar__group,
@@ -2404,24 +2404,24 @@ async function saveFeaturedOrder() {
.adminSidebar__groupTitle { .adminSidebar__groupTitle {
font-size: 13px; font-size: 13px;
font-weight: 800; font-weight: 800;
color: rgba(255, 255, 255, 0.84); color: var(--theme-text);
} }
.adminGamePicker { .adminGamePicker {
display: grid; display: grid;
gap: 8px; gap: 8px;
max-height: 320px; max-height: 640px;
overflow: auto; overflow: auto;
padding-right: 4px; padding-right: 4px;
} }
.adminGamePicker__item { .adminGamePicker__item {
display: grid; display: grid;
gap: 2px; /* gap: 2px; */
padding: 11px 12px; padding: 11px 12px;
text-align: left; text-align: left;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.9); color: var(--theme-text);
cursor: pointer; cursor: pointer;
} }
.adminGamePicker__item--active { .adminGamePicker__item--active {
@@ -2434,7 +2434,7 @@ async function saveFeaturedOrder() {
} }
.adminGamePicker__meta { .adminGamePicker__meta {
font-size: 11px; font-size: 11px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-soft);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -2444,12 +2444,12 @@ async function saveFeaturedOrder() {
gap: 4px; gap: 4px;
padding: 12px 14px; padding: 12px 14px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
} }
.sidebarStat__label { .sidebarStat__label {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-soft);
} }
.sidebarStat__value { .sidebarStat__value {
font-size: 14px; font-size: 14px;
@@ -2500,8 +2500,8 @@ async function saveFeaturedOrder() {
padding: 12px 14px; padding: 12px 14px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
font-weight: 800; font-weight: 800;
transition: transition:
@@ -2512,7 +2512,7 @@ async function saveFeaturedOrder() {
.tab:hover, .tab:hover,
.modeTab:hover { .modeTab:hover {
border-color: rgba(255, 255, 255, 0.18); border-color: rgba(255, 255, 255, 0.18);
background: rgba(255, 255, 255, 0.07); background: var(--theme-surface-soft-2);
transform: translateY(-1px); transform: translateY(-1px);
} }
.tab--active, .tab--active,
@@ -2529,8 +2529,8 @@ async function saveFeaturedOrder() {
.panel { .panel {
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
background: background:
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.018)), linear-gradient(180deg, var(--theme-surface-soft), var(--theme-pill-bg)),
rgba(34, 34, 34, 0.84); color-mix(in srgb, var(--theme-card-bg) 96%, transparent);
border-radius: 24px; border-radius: 24px;
padding: 18px; padding: 18px;
box-shadow: 0 18px 44px rgba(0, 0, 0, 0.18); box-shadow: 0 18px 44px rgba(0, 0, 0, 0.18);
@@ -2554,7 +2554,7 @@ async function saveFeaturedOrder() {
font-weight: 900; font-weight: 900;
} }
.emptyState__desc { .emptyState__desc {
color: rgba(255, 255, 255, 0.66); color: var(--theme-text-muted);
line-height: 1.6; line-height: 1.6;
} }
.featuredOrderPanel { .featuredOrderPanel {
@@ -2566,7 +2566,7 @@ async function saveFeaturedOrder() {
.featuredOrderPanel__list, .featuredOrderPanel__list,
.featuredOrderPanel__picker { .featuredOrderPanel__picker {
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.025); background: color-mix(in srgb, var(--theme-pill-bg) 85%, transparent);
border-radius: 18px; border-radius: 18px;
padding: 16px; padding: 16px;
} }
@@ -2585,8 +2585,8 @@ async function saveFeaturedOrder() {
align-items: center; align-items: center;
padding: 14px; padding: 14px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(0, 0, 0, 0.22); background: var(--theme-pill-bg);
} }
.featuredCard__meta { .featuredCard__meta {
display: flex; display: flex;
@@ -2630,9 +2630,9 @@ async function saveFeaturedOrder() {
align-items: center; align-items: center;
padding: 14px; padding: 14px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(0, 0, 0, 0.16); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
} }
@@ -2651,7 +2651,7 @@ async function saveFeaturedOrder() {
.section { .section {
margin-top: 18px; margin-top: 18px;
padding-top: 18px; padding-top: 18px;
border-top: 1px solid rgba(255, 255, 255, 0.08); border-top: 1px solid var(--theme-border);
} }
.section--topGrid { .section--topGrid {
display: grid; display: grid;
@@ -2674,13 +2674,13 @@ async function saveFeaturedOrder() {
} }
.adminCard { .adminCard {
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.025); background: color-mix(in srgb, var(--theme-pill-bg) 85%, transparent);
border-radius: 18px; border-radius: 18px;
padding: 16px; padding: 16px;
min-width: 0; min-width: 0;
} }
.adminCard--muted { .adminCard--muted {
background: rgba(255, 255, 255, 0.02); background: var(--theme-pill-bg);
} }
.sectionHeader { .sectionHeader {
display: flex; display: flex;
@@ -2725,8 +2725,8 @@ async function saveFeaturedOrder() {
padding: 11px 13px; padding: 11px 13px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
outline: none; outline: none;
/* margin-top: 10px; */ /* margin-top: 10px; */
} }
@@ -2777,7 +2777,7 @@ async function saveFeaturedOrder() {
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid rgba(255, 255, 255, 0.14);
background: rgba(255, 255, 255, 0.06); background: rgba(255, 255, 255, 0.06);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
font-weight: 800; font-weight: 800;
text-align: center; text-align: center;
@@ -2816,7 +2816,7 @@ async function saveFeaturedOrder() {
border-color: rgba(239, 68, 68, 0.28); border-color: rgba(239, 68, 68, 0.28);
} }
.btn--ghost { .btn--ghost {
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
} }
.detailHead { .detailHead {
display: flex; display: flex;
@@ -2845,12 +2845,12 @@ async function saveFeaturedOrder() {
object-fit: cover; object-fit: cover;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.selectedThumb--empty { .selectedThumb--empty {
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-soft);
} }
.selectedThumb--sidebar { .selectedThumb--sidebar {
width: 100%; width: 100%;
@@ -2872,7 +2872,7 @@ async function saveFeaturedOrder() {
overflow: hidden; overflow: hidden;
border-radius: 18px; border-radius: 18px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
text-align: left; text-align: left;
transition: border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease; transition: border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease;
} }
@@ -2888,7 +2888,7 @@ async function saveFeaturedOrder() {
place-items: center; place-items: center;
min-height: 52px; min-height: 52px;
padding: 12px 16px; padding: 12px 16px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(6, 9, 16, 0.86) 46%, rgba(6, 9, 16, 0.94) 100%); background: linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--theme-main-bg) 82%, transparent) 46%, color-mix(in srgb, var(--theme-main-bg) 94%, transparent) 100%);
} }
.thumbDropZone__title { .thumbDropZone__title {
font-weight: 900; font-weight: 900;
@@ -2910,8 +2910,8 @@ async function saveFeaturedOrder() {
.dropZone { .dropZone {
padding: 18px; padding: 18px;
border-radius: 16px; border-radius: 16px;
border: 1px dashed rgba(255, 255, 255, 0.2); border: 1px dashed var(--theme-border-strong);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
transition: transition:
border-color 0.16s ease, border-color 0.16s ease,
background 0.16s ease, background 0.16s ease,
@@ -2941,7 +2941,7 @@ async function saveFeaturedOrder() {
padding: 12px; padding: 12px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.itemPreviewGrid { .itemPreviewGrid {
display: grid; display: grid;
@@ -2964,7 +2964,7 @@ async function saveFeaturedOrder() {
overflow: hidden; overflow: hidden;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
} }
.itemDraftRow__body { .itemDraftRow__body {
min-width: 0; min-width: 0;
@@ -2976,7 +2976,7 @@ async function saveFeaturedOrder() {
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
} }
.itemPreviewImage { .itemPreviewImage {
width: 100%; width: 100%;
@@ -2987,7 +2987,7 @@ async function saveFeaturedOrder() {
min-height: 192px; min-height: 192px;
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-soft);
font-size: 13px; font-size: 13px;
text-align: center; text-align: center;
line-height: 1.5; line-height: 1.5;
@@ -3001,7 +3001,7 @@ async function saveFeaturedOrder() {
.thumbCard { .thumbCard {
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px; border-radius: 16px;
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
padding: 12px; padding: 12px;
min-width: 0; min-width: 0;
} }
@@ -3041,7 +3041,7 @@ async function saveFeaturedOrder() {
appearance: none; appearance: none;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 18px; border-radius: 18px;
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
overflow: hidden; overflow: hidden;
display: grid; display: grid;
gap: 10px; gap: 10px;
@@ -3062,7 +3062,7 @@ async function saveFeaturedOrder() {
object-fit: cover; object-fit: cover;
display: block; display: block;
border-radius: 14px; border-radius: 14px;
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
} }
.customItemCard__title { .customItemCard__title {
min-width: 0; min-width: 0;
@@ -3090,7 +3090,7 @@ async function saveFeaturedOrder() {
aspect-ratio: 1 / 1; aspect-ratio: 1 / 1;
object-fit: cover; object-fit: cover;
border-radius: 18px; border-radius: 18px;
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
} }
.customItemModal__body { .customItemModal__body {
@@ -3105,7 +3105,7 @@ async function saveFeaturedOrder() {
} }
.customItemModal__label { .customItemModal__label {
font-size: 11px; font-size: 11px;
color: rgba(255, 255, 255, 0.52); color: var(--theme-text-faint);
} }
.customItemModal__chips { .customItemModal__chips {
display: flex; display: flex;
@@ -3129,7 +3129,7 @@ async function saveFeaturedOrder() {
} }
.customItemModal__metaRow span { .customItemModal__metaRow span {
font-size: 11px; font-size: 11px;
color: rgba(255, 255, 255, 0.46); color: var(--theme-text-faint);
} }
.customItemModal__metaRow strong { .customItemModal__metaRow strong {
min-width: 0; min-width: 0;
@@ -3137,7 +3137,7 @@ async function saveFeaturedOrder() {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.84); color: var(--theme-text);
} }
.customItemModal__actions { .customItemModal__actions {
display: flex; display: flex;
@@ -3169,7 +3169,7 @@ async function saveFeaturedOrder() {
position: relative; position: relative;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 18px; border-radius: 18px;
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
padding: 24px 16px 16px; padding: 24px 16px 16px;
overflow: visible; overflow: visible;
} }
@@ -3253,7 +3253,7 @@ async function saveFeaturedOrder() {
inset: auto 0 0 0; inset: auto 0 0 0;
padding: 10px 0 6px; padding: 10px 0 6px;
background: linear-gradient(180deg, rgba(7, 10, 18, 0), rgba(7, 10, 18, 0.88)); background: linear-gradient(180deg, rgba(7, 10, 18, 0), rgba(7, 10, 18, 0.88));
color: rgba(255, 255, 255, 0.9); color: var(--theme-text);
font-size: 10px; font-size: 10px;
font-weight: 800; font-weight: 800;
opacity: 0; opacity: 0;
@@ -3296,7 +3296,7 @@ async function saveFeaturedOrder() {
} }
.userInfoLine span { .userInfoLine span {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-soft);
} }
.userInfoLine strong { .userInfoLine strong {
min-width: 0; min-width: 0;
@@ -3310,7 +3310,7 @@ async function saveFeaturedOrder() {
} }
.field__label { .field__label {
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-soft);
} }
.field__input { .field__input {
width: 100%; width: 100%;
@@ -3318,7 +3318,7 @@ async function saveFeaturedOrder() {
border: 0; border: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.12); border-bottom: 1px solid rgba(255, 255, 255, 0.12);
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.94); color: var(--theme-text-strong);
outline: none; outline: none;
font-size: 18px; font-size: 18px;
letter-spacing: -0.02em; letter-spacing: -0.02em;
@@ -3328,7 +3328,7 @@ async function saveFeaturedOrder() {
} }
.field__hint { .field__hint {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-faint);
} }
.userEditForm { .userEditForm {
@@ -3358,7 +3358,7 @@ async function saveFeaturedOrder() {
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(96, 165, 250, 0.28); border: 1px solid rgba(96, 165, 250, 0.28);
background: rgba(96, 165, 250, 0.1); background: rgba(96, 165, 250, 0.1);
color: rgba(191, 219, 254, 0.92); color: color-mix(in srgb, var(--theme-accent-bg) 80%, white);
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
} }
@@ -3377,11 +3377,11 @@ async function saveFeaturedOrder() {
padding: 0; padding: 0;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
cursor: pointer; cursor: pointer;
} }
.iconActionButton__icon { .iconActionButton__icon {
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
} }
.iconActionButton:disabled { .iconActionButton:disabled {
cursor: not-allowed; cursor: not-allowed;
@@ -3400,7 +3400,7 @@ async function saveFeaturedOrder() {
padding: 0; padding: 0;
border: 0; border: 0;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.46); color: var(--theme-text-faint);
font-size: 9px; font-size: 9px;
line-height: 1.4; line-height: 1.4;
letter-spacing: 0.01em; letter-spacing: 0.01em;
@@ -3421,7 +3421,7 @@ async function saveFeaturedOrder() {
padding: 18px; padding: 18px;
border-radius: 20px; border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
} }
.templateRequestCard__head { .templateRequestCard__head {
display: flex; display: flex;
@@ -3436,7 +3436,7 @@ async function saveFeaturedOrder() {
} }
.templateRequestCard__desc { .templateRequestCard__desc {
margin-top: 6px; margin-top: 6px;
color: rgba(255, 255, 255, 0.74); color: var(--theme-text-muted);
line-height: 1.55; line-height: 1.55;
white-space: pre-line; white-space: pre-line;
} }
@@ -3460,7 +3460,7 @@ async function saveFeaturedOrder() {
object-fit: cover; object-fit: cover;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.templateRequestItem__label { .templateRequestItem__label {
font-size: 12px; font-size: 12px;
@@ -3480,7 +3480,7 @@ async function saveFeaturedOrder() {
} }
.templateRequestField__label { .templateRequestField__label {
font-size: 11px; font-size: 11px;
color: rgba(255, 255, 255, 0.52); color: var(--theme-text-faint);
} }
.templateRequestCard__actions { .templateRequestCard__actions {
display: flex; display: flex;
@@ -3497,11 +3497,11 @@ async function saveFeaturedOrder() {
max-height: 240px; max-height: 240px;
object-fit: cover; object-fit: cover;
border-radius: 18px; border-radius: 18px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.requestPreview__desc { .requestPreview__desc {
color: rgba(255, 255, 255, 0.74); color: var(--theme-text-muted);
line-height: 1.6; line-height: 1.6;
white-space: pre-line; white-space: pre-line;
} }
@@ -3532,7 +3532,7 @@ async function saveFeaturedOrder() {
overflow: hidden; overflow: hidden;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
min-height: 72px; min-height: 72px;
} }
.requestPreview__item--muted { .requestPreview__item--muted {
@@ -3569,7 +3569,7 @@ async function saveFeaturedOrder() {
gap: 16px; gap: 16px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 20px; border-radius: 20px;
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
padding: 16px; padding: 16px;
} }
.tierAdminCard__preview { .tierAdminCard__preview {
@@ -3581,7 +3581,7 @@ async function saveFeaturedOrder() {
object-fit: cover; object-fit: cover;
display: block; display: block;
border-radius: 14px; border-radius: 14px;
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.tierAdminCard__thumb--empty { .tierAdminCard__thumb--empty {
background: linear-gradient(135deg, rgba(255,255,255,0.08), rgba(255,255,255,0.03)); background: linear-gradient(135deg, rgba(255,255,255,0.08), rgba(255,255,255,0.03));
@@ -3603,7 +3603,7 @@ async function saveFeaturedOrder() {
} }
.tierAdminCard__desc { .tierAdminCard__desc {
margin-top: 6px; margin-top: 6px;
color: rgba(255, 255, 255, 0.74); color: var(--theme-text-muted);
line-height: 1.5; line-height: 1.5;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
@@ -3627,7 +3627,7 @@ async function saveFeaturedOrder() {
padding: 7px 10px; padding: 7px 10px;
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.05); background: var(--theme-surface-soft);
font-size: 12px; font-size: 12px;
font-weight: 800; font-weight: 800;
} }
@@ -3641,8 +3641,8 @@ async function saveFeaturedOrder() {
gap: 10px; gap: 10px;
padding: 14px; padding: 14px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(0, 0, 0, 0.14); background: var(--theme-pill-bg);
} }
.tierAdminSection__title { .tierAdminSection__title {
font-weight: 800; font-weight: 800;
@@ -3663,9 +3663,9 @@ async function saveFeaturedOrder() {
justify-items: center; justify-items: center;
padding: 12px 10px; padding: 12px 10px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
min-width: 0; min-width: 0;
@@ -3691,7 +3691,7 @@ async function saveFeaturedOrder() {
display: grid; display: grid;
place-items: center; place-items: center;
padding: 20px; padding: 20px;
background: rgba(3, 7, 18, 0.66); background: color-mix(in srgb, var(--theme-body-bg) 76%, transparent);
backdrop-filter: blur(6px); backdrop-filter: blur(6px);
} }
.modalCard { .modalCard {
@@ -3701,7 +3701,7 @@ async function saveFeaturedOrder() {
padding: 20px; padding: 20px;
border-radius: 24px; border-radius: 24px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(11, 18, 32, 0.96); background: color-mix(in srgb, var(--theme-main-bg) 96%, transparent);
} }
.modalCard--preview { .modalCard--preview {
width: min(1200px, 100%); width: min(1200px, 100%);
@@ -3737,7 +3737,7 @@ async function saveFeaturedOrder() {
min-height: min(80vh, 820px); min-height: min(80vh, 820px);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px; border-radius: 16px;
background: rgba(255, 255, 255, 0.02); background: var(--theme-pill-bg);
} }
.importModeTabs { .importModeTabs {
display: flex; display: flex;

View File

@@ -110,16 +110,16 @@ onMounted(loadFavorites)
.select { .select {
padding: 11px 13px; padding: 11px 13px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.05); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
} }
.btn { .btn {
padding: 11px 13px; padding: 11px 13px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
font-weight: 800; font-weight: 800;
cursor: pointer; cursor: pointer;
} }
@@ -133,18 +133,18 @@ onMounted(loadFavorites)
} }
.boardCard { .boardCard {
border-radius: 22px; border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.16); border: 1px solid var(--theme-card-border);
background: rgba(62, 62, 62, 0.82); background: var(--theme-card-bg);
overflow: hidden; overflow: hidden;
display: grid; display: grid;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: inset 0 1px 0 var(--theme-card-shadow);
transition: transition:
transform 0.16s ease, transform 0.16s ease,
background 0.16s ease; background 0.16s ease;
} }
.boardCard:hover { .boardCard:hover {
transform: translateY(-2px); transform: translateY(-2px);
background: rgba(70, 70, 70, 0.96); background: var(--theme-card-bg-hover);
} }
.boardCard__body { .boardCard__body {
border: 0; border: 0;
@@ -172,10 +172,10 @@ onMounted(loadFavorites)
object-fit: cover; object-fit: cover;
} }
.boardCard__thumbPlaceholder { .boardCard__thumbPlaceholder {
background: #555; background: var(--theme-thumb-fallback-bg);
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.4); color: var(--theme-text-faint);
font-size: 13px; font-size: 13px;
font-weight: 700; font-weight: 700;
} }
@@ -222,7 +222,7 @@ onMounted(loadFavorites)
height: 22px; height: 22px;
border-radius: 9999px; border-radius: 9999px;
object-fit: cover; object-fit: cover;
background: rgba(255, 255, 255, 0.08); background: var(--theme-border);
flex: 0 0 auto; flex: 0 0 auto;
} }
.boardCard__avatar--fallback { .boardCard__avatar--fallback {
@@ -235,7 +235,7 @@ onMounted(loadFavorites)
.favoriteStat { .favoriteStat {
flex: 0 0 auto; flex: 0 0 auto;
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.64); color: var(--theme-text-faint);
white-space: nowrap; white-space: nowrap;
} }

View File

@@ -149,7 +149,7 @@ function submitSearch() {
} }
.dashboardHero__eyebrow { .dashboardHero__eyebrow {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.08em; letter-spacing: 0.08em;
} }
@@ -157,15 +157,15 @@ function submitSearch() {
margin: 4px 0 6px; margin: 4px 0 6px;
font-size: 32px; font-size: 32px;
letter-spacing: -0.04em; letter-spacing: -0.04em;
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
} }
.dashboardHero__desc { .dashboardHero__desc {
margin: 0; margin: 0;
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
max-width: 720px; max-width: 720px;
} }
.panel { .panel {
/* border: 1px solid rgba(255, 255, 255, 0.08); */ /* border: 1px solid var(--theme-border); */
background: transparent; background: transparent;
border-radius: 0; border-radius: 0;
padding: 0; padding: 0;
@@ -174,8 +174,8 @@ function submitSearch() {
margin: 10px 0 14px; margin: 10px 0 14px;
padding: 10px 12px; padding: 10px 12px;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(239, 68, 68, 0.3); border: 1px solid var(--theme-danger-border);
background: rgba(239, 68, 68, 0.12); background: var(--theme-danger-bg);
} }
.panel__title { .panel__title {
font-weight: 800; font-weight: 800;
@@ -183,7 +183,7 @@ function submitSearch() {
} }
.panel__sub { .panel__sub {
margin-top: 6px; margin-top: 6px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-muted);
font-size: 13px; font-size: 13px;
} }
.panel__head { .panel__head {
@@ -204,16 +204,16 @@ function submitSearch() {
min-width: 240px; min-width: 240px;
padding: 11px 13px; padding: 11px 13px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.05); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
} }
.searchBar__button { .searchBar__button {
padding: 11px 14px; padding: 11px 14px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
font-weight: 800; font-weight: 800;
cursor: pointer; cursor: pointer;
} }
@@ -232,18 +232,18 @@ function submitSearch() {
.boardCard { .boardCard {
min-width: 0; min-width: 0;
border-radius: 22px; border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.16); border: 1px solid var(--theme-card-border);
background: rgba(62, 62, 62, 0.82); background: var(--theme-card-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
display: grid; display: grid;
overflow: hidden; overflow: hidden;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: inset 0 1px 0 var(--theme-card-shadow);
transition: transition:
transform 0.16s ease, transform 0.16s ease,
background 0.16s ease; background 0.16s ease;
} }
.boardCard:hover { .boardCard:hover {
background: rgba(70, 70, 70, 0.96); background: var(--theme-card-bg-hover);
transform: translateY(-2px); transform: translateY(-2px);
} }
.boardCard__body { .boardCard__body {
@@ -293,10 +293,10 @@ function submitSearch() {
.boardCard__thumbPlaceholder { .boardCard__thumbPlaceholder {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: #555; background: var(--theme-thumb-fallback-bg);
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.4); color: var(--theme-text-faint);
font-size: 13px; font-size: 13px;
font-weight: 700; font-weight: 700;
border-radius: 18px; border-radius: 18px;
@@ -362,7 +362,7 @@ function submitSearch() {
border-radius: 9999px; border-radius: 9999px;
object-fit: cover; object-fit: cover;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.08); background: var(--theme-border);
flex: 0 0 auto; flex: 0 0 auto;
} }
.boardCard__avatar--fallback { .boardCard__avatar--fallback {
@@ -377,7 +377,7 @@ function submitSearch() {
min-width: 0; min-width: 0;
max-width: 100%; max-width: 100%;
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.64); color: var(--theme-text-faint);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@@ -120,31 +120,31 @@ function thumbUrl(g) {
margin: 0 0 16px; margin: 0 0 16px;
padding: 10px 12px; padding: 10px 12px;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(239, 68, 68, 0.18); border: 1px solid var(--theme-danger-border);
background: rgba(239, 68, 68, 0.1); background: var(--theme-danger-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
} }
.pageHead__searchState { .pageHead__searchState {
margin-top: 8px; margin-top: 8px;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-muted);
} }
.libraryCard { .libraryCard {
position: relative; position: relative;
text-align: left; text-align: left;
padding: 14px; padding: 14px;
border-radius: 22px; border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.16); border: 1px solid var(--theme-card-border);
background: rgba(62, 62, 62, 0.82); background: var(--theme-card-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
display: grid; display: grid;
gap: 12px; gap: 12px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: inset 0 1px 0 var(--theme-card-shadow);
transition: transform 0.16s ease, background 0.16s ease; transition: transform 0.16s ease, background 0.16s ease;
will-change: transform, opacity; will-change: transform, opacity;
} }
.libraryCard:hover { .libraryCard:hover {
background: rgba(70, 70, 70, 0.96); background: var(--theme-card-bg-hover);
transform: translateY(-2px); transform: translateY(-2px);
} }
.libraryCard__main { .libraryCard__main {
@@ -191,8 +191,8 @@ function thumbUrl(g) {
width: 100%; width: 100%;
aspect-ratio: 16 / 9; aspect-ratio: 16 / 9;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.06); border: 1px solid var(--theme-surface-soft-2);
background: #555; background: var(--theme-thumb-fallback-bg);
overflow: hidden; overflow: hidden;
display: grid; display: grid;
place-items: center; place-items: center;
@@ -204,7 +204,7 @@ function thumbUrl(g) {
} }
.libraryCard__thumbFallback { .libraryCard__thumbFallback {
font-size: 14px; font-size: 14px;
color: rgba(255, 255, 255, 0.4); color: var(--theme-text-faint);
} }
.libraryCard__body { .libraryCard__body {
display: grid; display: grid;
@@ -241,7 +241,7 @@ function thumbUrl(g) {
.libraryEmpty { .libraryEmpty {
padding: 20px 0; padding: 20px 0;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-muted);
} }
@media (max-width: 1400px) { @media (max-width: 1400px) {
.libraryGrid { .libraryGrid {

View File

@@ -30,8 +30,15 @@ const description = computed(() =>
: '저장한 티어표와 즐겨찾기, 프로필 설정을 이어서 관리할 수 있어요.' : '저장한 티어표와 즐겨찾기, 프로필 설정을 이어서 관리할 수 있어요.'
) )
const submitLabel = computed(() => (mode.value === 'signup' ? '가입하기' : '로그인')) const submitLabel = computed(() => (mode.value === 'signup' ? '가입하기' : '로그인'))
const authReady = computed(() => auth.hydrated)
const checkingSession = computed(() => !authReady.value || auth.status === 'loading')
onMounted(async () => { onMounted(async () => {
if (!auth.hydrated) await auth.refresh()
if (auth.user) {
router.replace(typeof route.query.redirect === 'string' ? route.query.redirect : '/me')
return
}
try { try {
const meta = await api.authMeta() const meta = await api.authMeta()
hasUsers.value = !!meta.hasUsers hasUsers.value = !!meta.hasUsers
@@ -40,6 +47,15 @@ onMounted(async () => {
} }
}) })
watch(
() => [auth.hydrated, auth.user],
([hydrated, user]) => {
if (!hydrated || !user) return
router.replace(typeof route.query.redirect === 'string' ? route.query.redirect : '/me')
},
{ immediate: true }
)
async function submit() { async function submit() {
error.value = '' error.value = ''
if (mode.value === 'signup' && password.value !== passwordConfirm.value) { if (mode.value === 'signup' && password.value !== passwordConfirm.value) {
@@ -66,7 +82,11 @@ async function submit() {
</div> </div>
</header> </header>
<section class="authScreen"> <section v-if="checkingSession" class="authScreen authScreen--loading">
<div class="authLoading">로그인 상태를 확인하고 있어요.</div>
</section>
<section v-else class="authScreen">
<div class="authTabs" role="tablist" aria-label="로그인 또는 회원가입"> <div class="authTabs" role="tablist" aria-label="로그인 또는 회원가입">
<button type="button" class="authTabs__button" :class="{ 'authTabs__button--active': mode === 'login' }" @click="mode = 'login'"> <button type="button" class="authTabs__button" :class="{ 'authTabs__button--active': mode === 'login' }" @click="mode = 'login'">
로그인 로그인
@@ -128,14 +148,24 @@ async function submit() {
padding-top: 4px; padding-top: 4px;
} }
.authScreen--loading {
min-height: 220px;
align-items: center;
}
.authLoading {
color: var(--theme-text-muted);
font-size: 15px;
}
.authTabs { .authTabs {
display: inline-flex; display: inline-flex;
gap: 8px; gap: 8px;
width: fit-content; width: fit-content;
padding: 6px; padding: 6px;
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
} }
.authTabs__button { .authTabs__button {
@@ -144,14 +174,14 @@ async function submit() {
border: 0; border: 0;
border-radius: 999px; border-radius: 999px;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-muted);
font-weight: 700; font-weight: 700;
cursor: pointer; cursor: pointer;
} }
.authTabs__button--active { .authTabs__button--active {
background: rgba(76, 133, 245, 0.22); background: rgba(76, 133, 245, 0.22);
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
} }
.authFields { .authFields {
@@ -166,16 +196,16 @@ async function submit() {
.field__label { .field__label {
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-muted);
} }
.field__input { .field__input {
width: 100%; width: 100%;
padding: 14px 0; padding: 14px 0;
border: 0; border: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.12); border-bottom: 1px solid var(--theme-border-strong);
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.94); color: var(--theme-text);
outline: none; outline: none;
font-size: 18px; font-size: 18px;
letter-spacing: -0.02em; letter-spacing: -0.02em;
@@ -187,7 +217,7 @@ async function submit() {
.field__hint { .field__hint {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
} }
.roleBadge { .roleBadge {
@@ -196,7 +226,7 @@ async function submit() {
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(96, 165, 250, 0.28); border: 1px solid rgba(96, 165, 250, 0.28);
background: rgba(96, 165, 250, 0.1); background: rgba(96, 165, 250, 0.1);
color: rgba(191, 219, 254, 0.92); color: var(--theme-text);
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
} }
@@ -218,14 +248,14 @@ async function submit() {
.primaryAction { .primaryAction {
border: 1px solid rgba(76, 133, 245, 0.96); border: 1px solid rgba(76, 133, 245, 0.96);
background: rgba(76, 133, 245, 0.92); background: var(--theme-accent-bg);
color: #fff; color: var(--theme-accent-text);
} }
.secondaryAction { .secondaryAction {
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.86); color: var(--theme-text);
} }
@media (max-width: 720px) { @media (max-width: 720px) {

View File

@@ -124,7 +124,7 @@ function openList(t) {
} }
.dashboardHero__eyebrow { .dashboardHero__eyebrow {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.08em; letter-spacing: 0.08em;
} }
@@ -132,11 +132,11 @@ function openList(t) {
margin: 4px 0 6px; margin: 4px 0 6px;
font-size: 32px; font-size: 32px;
letter-spacing: -0.04em; letter-spacing: -0.04em;
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
} }
.dashboardHero__desc { .dashboardHero__desc {
margin: 0; margin: 0;
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
max-width: 720px; max-width: 720px;
} }
.panel { .panel {
@@ -155,18 +155,18 @@ function openList(t) {
.boardCard { .boardCard {
min-width: 0; min-width: 0;
border-radius: 22px; border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.16); border: 1px solid var(--theme-card-border);
background: rgba(62, 62, 62, 0.82); background: var(--theme-card-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
overflow: hidden; overflow: hidden;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: inset 0 1px 0 var(--theme-card-shadow);
transition: transition:
transform 0.16s ease, transform 0.16s ease,
background 0.16s ease; background 0.16s ease;
} }
.boardCard:hover { .boardCard:hover {
transform: translateY(-2px); transform: translateY(-2px);
background: rgba(70, 70, 70, 0.96); background: var(--theme-card-bg-hover);
} }
.boardCard__body { .boardCard__body {
min-width: 0; min-width: 0;
@@ -197,10 +197,10 @@ function openList(t) {
.boardCard__thumbPlaceholder { .boardCard__thumbPlaceholder {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: #555; background: var(--theme-thumb-fallback-bg);
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.4); color: var(--theme-text-faint);
font-size: 13px; font-size: 13px;
font-weight: 700; font-weight: 700;
border-radius: 18px; border-radius: 18px;
@@ -259,7 +259,7 @@ function openList(t) {
border-radius: 9999px; border-radius: 9999px;
object-fit: cover; object-fit: cover;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.08); background: var(--theme-border);
flex: 0 0 auto; flex: 0 0 auto;
} }
.boardCard__avatar--fallback { .boardCard__avatar--fallback {
@@ -274,7 +274,7 @@ function openList(t) {
min-width: 0; min-width: 0;
max-width: 100%; max-width: 100%;
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.64); color: var(--theme-text-faint);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@@ -30,14 +30,19 @@ const avatarUrl = computed(() => {
return toApiUrl(auth.user.avatarSrc) return toApiUrl(auth.user.avatarSrc)
}) })
const authReady = computed(() => auth.hydrated)
const displayInitial = computed(() => { const displayInitial = computed(() => {
const email = auth.user?.email || 'U' const email = auth.user?.email || 'U'
return email[0].toUpperCase() return email[0].toUpperCase()
}) })
onMounted(async () => { onMounted(async () => {
await auth.refresh() if (!auth.hydrated) await auth.refresh()
if (!auth.user) router.push('/login') if (!auth.user) {
router.replace('/login')
return
}
nickname.value = auth.user?.nickname || '' nickname.value = auth.user?.nickname || ''
removeAvatar.value = false removeAvatar.value = false
}) })
@@ -121,7 +126,11 @@ async function logout() {
</div> </div>
</header> </header>
<section v-if="auth.user" class="settingsScreen"> <section v-if="!authReady" class="settingsScreen settingsScreen--loading">
<div class="settingsLoading">계정 정보를 불러오고 있어요.</div>
</section>
<section v-else-if="auth.user" class="settingsScreen">
<div class="settingsIdentity"> <div class="settingsIdentity">
<div class="avatarButtonWrap"> <div class="avatarButtonWrap">
<button class="avatarButton" type="button" @click="openAvatarPicker"> <button class="avatarButton" type="button" @click="openAvatarPicker">
@@ -185,6 +194,16 @@ async function logout() {
padding-top: 4px; padding-top: 4px;
} }
.settingsScreen--loading {
min-height: 240px;
align-items: center;
}
.settingsLoading {
color: var(--theme-text-muted);
font-size: 15px;
}
.settingsIdentity { .settingsIdentity {
display: grid; display: grid;
grid-template-columns: 120px minmax(0, 1fr); grid-template-columns: 120px minmax(0, 1fr);
@@ -202,15 +221,15 @@ async function logout() {
position: relative; position: relative;
width: 120px; width: 120px;
height: 120px; height: 120px;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border-strong);
border-radius: 9999px; border-radius: 9999px;
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
overflow: hidden; overflow: hidden;
cursor: pointer; cursor: pointer;
display: grid; display: grid;
place-items: center; place-items: center;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: var(--theme-card-shadow);
} }
.avatarButton__image { .avatarButton__image {
@@ -222,7 +241,7 @@ async function logout() {
.avatarButton__fallback { .avatarButton__fallback {
font-size: 34px; font-size: 34px;
font-weight: 900; font-weight: 900;
color: rgba(255, 255, 255, 0.86); color: var(--theme-text);
} }
.avatarButton__overlay { .avatarButton__overlay {
@@ -232,7 +251,7 @@ async function logout() {
background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.72)); background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.72));
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
color: rgba(255, 255, 255, 0.82); color: var(--theme-text);
} }
.avatarButton__remove { .avatarButton__remove {
@@ -243,8 +262,8 @@ async function logout() {
height: 30px; height: 30px;
border: 0; border: 0;
border-radius: 999px; border-radius: 999px;
background: rgba(10, 10, 10, 0.72); background: var(--theme-shell-bg);
color: rgba(255, 255, 255, 0.88); color: var(--theme-text);
display: grid; display: grid;
place-items: center; place-items: center;
cursor: pointer; cursor: pointer;
@@ -264,7 +283,7 @@ async function logout() {
.avatarButton__remove:hover { .avatarButton__remove:hover {
background: rgba(190, 24, 24, 0.88); background: rgba(190, 24, 24, 0.88);
color: #fff; color: var(--theme-accent-text);
} }
.identityMeta { .identityMeta {
@@ -276,7 +295,7 @@ async function logout() {
font-size: 11px; font-size: 11px;
letter-spacing: 0.12em; letter-spacing: 0.12em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.36); color: var(--theme-text-soft);
} }
.identityMeta__title { .identityMeta__title {
@@ -286,7 +305,7 @@ async function logout() {
} }
.identityMeta__desc { .identityMeta__desc {
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
line-height: 1.6; line-height: 1.6;
} }
@@ -307,16 +326,16 @@ async function logout() {
.field__label { .field__label {
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-muted);
} }
.field__input { .field__input {
width: 100%; width: 100%;
padding: 14px 0; padding: 14px 0;
border: 0; border: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.12); border-bottom: 1px solid var(--theme-border-strong);
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.94); color: var(--theme-text);
outline: none; outline: none;
font-size: 18px; font-size: 18px;
letter-spacing: -0.02em; letter-spacing: -0.02em;
@@ -327,12 +346,12 @@ async function logout() {
} }
.field__input--readonly { .field__input--readonly {
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
} }
.field__hint { .field__hint {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
} }
.roleBadge { .roleBadge {
@@ -341,7 +360,7 @@ async function logout() {
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(96, 165, 250, 0.28); border: 1px solid rgba(96, 165, 250, 0.28);
background: rgba(96, 165, 250, 0.1); background: rgba(96, 165, 250, 0.1);
color: rgba(191, 219, 254, 0.92); color: var(--theme-text);
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
} }
@@ -363,14 +382,14 @@ async function logout() {
.primaryAction { .primaryAction {
border: 1px solid rgba(76, 133, 245, 0.96); border: 1px solid rgba(76, 133, 245, 0.96);
background: rgba(76, 133, 245, 0.92); background: var(--theme-accent-bg);
color: #fff; color: var(--theme-accent-text);
} }
.secondaryAction { .secondaryAction {
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.86); color: var(--theme-text);
} }
@media (max-width: 720px) { @media (max-width: 720px) {

View File

@@ -122,24 +122,24 @@ watch(
font-size: 11px; font-size: 11px;
letter-spacing: 0.12em; letter-spacing: 0.12em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.42); color: var(--theme-text-soft);
} }
.title { .title {
margin: 4px 0 0; margin: 4px 0 0;
font-size: 32px; font-size: 32px;
color: rgba(255, 255, 255, 0.96); color: var(--theme-text-strong);
letter-spacing: -0.04em; letter-spacing: -0.04em;
} }
.desc { .desc {
margin-top: 6px; margin-top: 6px;
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-muted);
} }
.error { .error {
margin: 0 0 8px; margin: 0 0 8px;
padding: 10px 12px; padding: 10px 12px;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(239, 68, 68, 0.18); border: 1px solid var(--theme-danger-border);
background: rgba(239, 68, 68, 0.1); background: var(--theme-danger-bg);
} }
.empty { .empty {
opacity: 0.76; opacity: 0.76;
@@ -151,16 +151,16 @@ watch(
} }
.boardCard { .boardCard {
border-radius: 22px; border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.16); border: 1px solid var(--theme-card-border);
background: rgba(62, 62, 62, 0.82); background: var(--theme-card-bg);
overflow: hidden; overflow: hidden;
display: grid; display: grid;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: inset 0 1px 0 var(--theme-card-shadow);
transition: transform 0.16s ease, background 0.16s ease; transition: transform 0.16s ease, background 0.16s ease;
} }
.boardCard:hover { .boardCard:hover {
transform: translateY(-2px); transform: translateY(-2px);
background: rgba(70, 70, 70, 0.96); background: var(--theme-card-bg-hover);
} }
.boardCard__body { .boardCard__body {
border: 0; border: 0;
@@ -188,10 +188,10 @@ watch(
object-fit: cover; object-fit: cover;
} }
.boardCard__thumbPlaceholder { .boardCard__thumbPlaceholder {
background: #555; background: var(--theme-thumb-fallback-bg);
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.4); color: var(--theme-text-faint);
font-size: 13px; font-size: 13px;
font-weight: 700; font-weight: 700;
} }
@@ -238,7 +238,7 @@ watch(
height: 22px; height: 22px;
border-radius: 9999px; border-radius: 9999px;
object-fit: cover; object-fit: cover;
background: rgba(255, 255, 255, 0.08); background: var(--theme-border);
flex: 0 0 auto; flex: 0 0 auto;
} }
.boardCard__avatar--fallback { .boardCard__avatar--fallback {
@@ -251,7 +251,7 @@ watch(
.favoriteStat { .favoriteStat {
flex: 0 0 auto; flex: 0 0 auto;
font-size: 13px; font-size: 13px;
color: rgba(255, 255, 255, 0.64); color: var(--theme-text-faint);
white-space: nowrap; white-space: nowrap;
} }

View File

@@ -1361,7 +1361,7 @@ onUnmounted(() => {
letter-spacing: -0.04em; letter-spacing: -0.04em;
} }
.editorMain__subtitle { .editorMain__subtitle {
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-soft);
font-size: 13px; font-size: 13px;
line-height: 1.5; line-height: 1.5;
} }
@@ -1372,13 +1372,13 @@ onUnmounted(() => {
gap: 8px; gap: 8px;
flex-wrap: wrap; flex-wrap: wrap;
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.62); color: var(--theme-text-soft);
} }
.editorMain__sourceLink { .editorMain__sourceLink {
border: 0; border: 0;
padding: 0; padding: 0;
background: transparent; background: transparent;
color: rgba(191, 219, 254, 0.94); color: color-mix(in srgb, var(--theme-accent-bg) 78%, white);
font: inherit; font: inherit;
cursor: pointer; cursor: pointer;
} }
@@ -1388,7 +1388,7 @@ onUnmounted(() => {
box-sizing: border-box; box-sizing: border-box;
background: background:
radial-gradient(circle at top, rgba(96, 165, 250, 0.14), transparent 38%), radial-gradient(circle at top, rgba(96, 165, 250, 0.14), transparent 38%),
rgba(11, 18, 32, 0.98); var(--theme-shell-bg);
} }
.previewOnly__sheet { .previewOnly__sheet {
display: grid; display: grid;
@@ -1451,13 +1451,13 @@ onUnmounted(() => {
text-align: center; text-align: center;
font-weight: 900; font-weight: 900;
border-radius: 14px; border-radius: 14px;
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
} }
.previewOnly__drop { .previewOnly__drop {
border-radius: 14px; border-radius: 14px;
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border);
min-height: calc(var(--thumb-size, 80px) + 24px); min-height: calc(var(--thumb-size, 80px) + 24px);
padding: 10px; padding: 10px;
display: flex; display: flex;
@@ -1498,8 +1498,8 @@ onUnmounted(() => {
gap: 12px; gap: 12px;
padding: 10px 12px; padding: 10px 12px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }
@@ -1513,8 +1513,8 @@ onUnmounted(() => {
width: 42px; width: 42px;
height: 24px; height: 24px;
border-radius: 999px; border-radius: 999px;
background: rgba(255, 255, 255, 0.16); background: var(--theme-surface-soft-3);
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
transition: background 180ms ease, border-color 180ms ease; transition: background 180ms ease, border-color 180ms ease;
flex: 0 0 auto; flex: 0 0 auto;
} }
@@ -1525,13 +1525,13 @@ onUnmounted(() => {
width: 18px; width: 18px;
height: 18px; height: 18px;
border-radius: 999px; border-radius: 999px;
background: rgba(255, 255, 255, 0.94); background: var(--theme-text-strong);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.24); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.24);
transition: transform 180ms ease; transition: transform 180ms ease;
} }
.toggleSwitch__label { .toggleSwitch__label {
font-weight: 800; font-weight: 800;
color: rgba(255, 255, 255, 0.9); color: var(--theme-text);
} }
.toggleSwitch input:checked ~ .toggleSwitch__track { .toggleSwitch input:checked ~ .toggleSwitch__track {
background: rgba(96, 165, 250, 0.34); background: rgba(96, 165, 250, 0.34);
@@ -1547,14 +1547,14 @@ onUnmounted(() => {
.btn { .btn {
padding: 10px 12px; padding: 10px 12px;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
font-weight: 700; font-weight: 700;
} }
.btn:hover { .btn:hover {
background: rgba(255, 255, 255, 0.08); background: var(--theme-surface-soft-3);
} }
.btn--primary { .btn--primary {
background: rgba(110, 231, 183, 0.18); background: rgba(110, 231, 183, 0.18);
@@ -1600,8 +1600,8 @@ onUnmounted(() => {
} }
.board { .board {
width: min(100%, 960px); width: min(100%, 960px);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border);
background: linear-gradient(180deg, rgba(55, 55, 55, 0.86), rgba(42, 42, 42, 0.82)); background: linear-gradient(180deg, color-mix(in srgb, var(--theme-card-bg) 94%, transparent), color-mix(in srgb, var(--theme-card-bg-hover) 88%, transparent));
border-radius: 22px; border-radius: 22px;
padding: 20px; padding: 20px;
align-self: start; align-self: start;
@@ -1614,15 +1614,15 @@ onUnmounted(() => {
display: grid; display: grid;
place-items: center; place-items: center;
padding: 20px; padding: 20px;
background: rgba(4, 8, 16, 0.68); background: color-mix(in srgb, var(--theme-body-bg) 76%, transparent);
backdrop-filter: blur(4px); backdrop-filter: blur(4px);
} }
.modalCard { .modalCard {
width: min(100%, 420px); width: min(100%, 420px);
border-radius: 20px; border-radius: 20px;
padding: 24px; padding: 24px;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--theme-border-strong);
background: linear-gradient(180deg, rgba(17, 24, 39, 0.96), rgba(11, 18, 32, 0.96)); background: linear-gradient(180deg, color-mix(in srgb, var(--theme-main-bg) 98%, transparent), color-mix(in srgb, var(--theme-shell-bg) 98%, transparent));
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.38); box-shadow: 0 24px 60px rgba(0, 0, 0, 0.38);
display: grid; display: grid;
gap: 10px; gap: 10px;
@@ -1695,24 +1695,24 @@ onUnmounted(() => {
} }
.templateRequestDraft__label { .templateRequestDraft__label {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.64); color: var(--theme-text-soft);
} }
.templateRequestDraft__hint { .templateRequestDraft__hint {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.46); color: var(--theme-text-faint);
} }
.templateRequestDraft__note { .templateRequestDraft__note {
font-size: 12px; font-size: 12px;
line-height: 1.6; line-height: 1.6;
color: rgba(255, 255, 255, 0.6); color: var(--theme-text-soft);
} }
.templateRequestDraft__input { .templateRequestDraft__input {
width: 100%; width: 100%;
padding: 14px 0; padding: 14px 0;
border: 0; border: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.12); border-bottom: 1px solid var(--theme-border-strong);
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.94); color: var(--theme-text-strong);
outline: none; outline: none;
font-size: 18px; font-size: 18px;
line-height: 1.5; line-height: 1.5;
@@ -1723,7 +1723,7 @@ onUnmounted(() => {
border-bottom-color: rgba(96, 165, 250, 0.9); border-bottom-color: rgba(96, 165, 250, 0.9);
} }
.templateRequestDraft__input::placeholder { .templateRequestDraft__input::placeholder {
color: rgba(255, 255, 255, 0.34); color: var(--theme-text-faint);
} }
.templateRequestDraft__textarea { .templateRequestDraft__textarea {
min-height: 92px; min-height: 92px;
@@ -1738,8 +1738,8 @@ onUnmounted(() => {
flex-wrap: wrap; flex-wrap: wrap;
padding: 10px 12px; padding: 10px 12px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
} }
.boardTools__left, .boardTools__left,
.boardTools__right { .boardTools__right {
@@ -1758,9 +1758,9 @@ onUnmounted(() => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.9); color: var(--theme-text);
cursor: pointer; cursor: pointer;
transition: background 160ms ease, border-color 160ms ease, color 160ms ease; transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
} }
@@ -1811,9 +1811,9 @@ onUnmounted(() => {
min-width: 48px; min-width: 48px;
padding: 9px 10px; padding: 9px 10px;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.05); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
cursor: pointer; cursor: pointer;
font-weight: 800; font-weight: 800;
} }
@@ -1831,7 +1831,7 @@ onUnmounted(() => {
border-radius: 28px; border-radius: 28px;
background: background:
radial-gradient(circle at top, rgba(96, 165, 250, 0.14), transparent 38%), radial-gradient(circle at top, rgba(96, 165, 250, 0.14), transparent 38%),
rgba(11, 18, 32, 0.98); var(--theme-shell-bg);
} }
.exportBoard__title { .exportBoard__title {
font-size: 28px; font-size: 28px;
@@ -1869,8 +1869,8 @@ onUnmounted(() => {
.row__label { .row__label {
position: relative; position: relative;
border-radius: 16px; border-radius: 16px;
background: rgba(255, 255, 255, 0.08); background: var(--theme-surface-soft-3);
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -1898,9 +1898,9 @@ onUnmounted(() => {
.columnName { .columnName {
width: 100%; width: 100%;
border: 0; border: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.12); border-bottom: 1px solid var(--theme-border-strong);
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.88); color: var(--theme-text);
padding: 4px 0; padding: 4px 0;
text-align: center; text-align: center;
font-size: 12px; font-size: 12px;
@@ -1909,7 +1909,7 @@ onUnmounted(() => {
outline: none; outline: none;
} }
.columnName::placeholder { .columnName::placeholder {
color: rgba(255, 255, 255, 0.34); color: var(--theme-text-faint);
} }
.columnRemoveText { .columnRemoveText {
position: absolute; position: absolute;
@@ -1924,15 +1924,15 @@ onUnmounted(() => {
border: 0; border: 0;
border-radius: 999px; border-radius: 999px;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-soft);
font-size: 16px; font-size: 16px;
line-height: 1; line-height: 1;
font-weight: 800; font-weight: 800;
cursor: pointer; cursor: pointer;
} }
.columnRemoveText:hover { .columnRemoveText:hover {
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
} }
.columnRemoveText:disabled { .columnRemoveText:disabled {
opacity: 0.32; opacity: 0.32;
@@ -1949,15 +1949,15 @@ onUnmounted(() => {
display: grid; display: grid;
place-items: center; place-items: center;
border-radius: 8px; border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border);
background: rgba(0, 0, 0, 0.16); background: rgba(0, 0, 0, 0.16);
font-size: 12px; font-size: 12px;
} }
.groupName { .groupName {
width: 100%; width: 100%;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--theme-border-strong);
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
border-radius: 10px; border-radius: 10px;
padding: 8px 10px; padding: 8px 10px;
font-weight: 900; font-weight: 900;
@@ -1977,15 +1977,15 @@ onUnmounted(() => {
border: 0; border: 0;
border-radius: 999px; border-radius: 999px;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.6); color: var(--theme-text-soft);
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
line-height: 1; line-height: 1;
font-weight: 800; font-weight: 800;
} }
.rowRemoveText:hover { .rowRemoveText:hover {
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
} }
.rowRemoveText:disabled { .rowRemoveText:disabled {
opacity: 0.32; opacity: 0.32;
@@ -1999,7 +1999,7 @@ onUnmounted(() => {
} }
.row__drop { .row__drop {
border-radius: 16px; border-radius: 16px;
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
border: 1px solid rgba(255, 255, 255, 0.10); border: 1px solid rgba(255, 255, 255, 0.10);
min-height: calc(var(--thumb-size, 80px) + 24px); min-height: calc(var(--thumb-size, 80px) + 24px);
padding: 10px; padding: 10px;
@@ -2055,7 +2055,7 @@ onUnmounted(() => {
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(239, 68, 68, 0.32); border: 1px solid rgba(239, 68, 68, 0.32);
background: rgba(11, 18, 32, 0.92); background: rgba(11, 18, 32, 0.92);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
font-size: 16px; font-size: 16px;
line-height: 1; line-height: 1;
font-weight: 900; font-weight: 900;
@@ -2070,14 +2070,14 @@ onUnmounted(() => {
width: var(--thumb-size, 80px); width: var(--thumb-size, 80px);
height: var(--thumb-size, 80px); height: var(--thumb-size, 80px);
border-radius: 10px; border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--theme-border-strong);
background: rgba(255, 255, 255, 0.06); background: var(--theme-surface-soft-2);
object-fit: cover; object-fit: cover;
} }
.sidebar { .sidebar {
min-width: 0; min-width: 0;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid var(--theme-border);
background: linear-gradient(180deg, rgba(52, 52, 52, 0.84), rgba(36, 36, 36, 0.8)); background: linear-gradient(180deg, color-mix(in srgb, var(--theme-card-bg) 94%, transparent), color-mix(in srgb, var(--theme-card-bg-hover) 88%, transparent));
border-radius: 22px; border-radius: 22px;
padding: 14px; padding: 14px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
@@ -2114,7 +2114,7 @@ onUnmounted(() => {
.editorSidebar__label { .editorSidebar__label {
font-size: 11px; font-size: 11px;
font-weight: 800; font-weight: 800;
color: rgba(255, 255, 255, 0.52); color: var(--theme-text-faint);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.12em; letter-spacing: 0.12em;
} }
@@ -2122,9 +2122,9 @@ onUnmounted(() => {
.editorSidebar__textarea { .editorSidebar__textarea {
width: 100%; width: 100%;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
padding: 11px 12px; padding: 11px 12px;
outline: none; outline: none;
resize: vertical; resize: vertical;
@@ -2135,7 +2135,7 @@ onUnmounted(() => {
.editorSidebar__hint { .editorSidebar__hint {
font-size: 12px; font-size: 12px;
line-height: 1.5; line-height: 1.5;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-soft);
word-break: keep-all; word-break: keep-all;
} }
.editorSidebar__hint--warn { .editorSidebar__hint--warn {
@@ -2147,8 +2147,8 @@ onUnmounted(() => {
aspect-ratio: 16 / 9; aspect-ratio: 16 / 9;
border-radius: 16px; border-radius: 16px;
overflow: hidden; overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: #4c4c4c; background: var(--theme-thumb-fallback-bg);
} }
.editorSidebar__thumbFrame--active { .editorSidebar__thumbFrame--active {
@@ -2165,7 +2165,7 @@ onUnmounted(() => {
height: 100%; height: 100%;
display: grid; display: grid;
place-items: center; place-items: center;
color: rgba(255, 255, 255, 0.36); color: var(--theme-text-faint);
font-size: 13px; font-size: 13px;
} }
@@ -2184,7 +2184,7 @@ onUnmounted(() => {
} }
.editorSidebar__fileName { .editorSidebar__fileName {
font-size: 12px; font-size: 12px;
color: rgba(255, 255, 255, 0.56); color: var(--theme-text-soft);
word-break: break-word; word-break: break-word;
} }
.editorSidebar__favorite { .editorSidebar__favorite {
@@ -2195,9 +2195,9 @@ onUnmounted(() => {
width: 100%; width: 100%;
padding: 11px 12px; padding: 11px 12px;
border-radius: 14px; border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid var(--theme-border);
background: rgba(255, 255, 255, 0.03); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.9); color: var(--theme-text);
font-weight: 800; font-weight: 800;
cursor: pointer; cursor: pointer;
} }
@@ -2223,7 +2223,7 @@ onUnmounted(() => {
border: 0; border: 0;
padding: 0; padding: 0;
background: transparent; background: transparent;
color: rgba(255, 255, 255, 0.74); color: var(--theme-text-muted);
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
} }
@@ -2285,16 +2285,16 @@ onUnmounted(() => {
height: 44px; height: 44px;
border-radius: 10px; border-radius: 10px;
object-fit: cover; object-fit: cover;
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--theme-border-strong);
} }
.customItemEditor__input { .customItemEditor__input {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
padding: 9px 10px; padding: 9px 10px;
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.12); border: 1px solid var(--theme-border-strong);
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
color: rgba(255, 255, 255, 0.92); color: var(--theme-text);
outline: none; outline: none;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -2303,7 +2303,7 @@ onUnmounted(() => {
padding: 14px; padding: 14px;
border-radius: 16px; border-radius: 16px;
border: 1px dashed rgba(255, 255, 255, 0.18); border: 1px dashed rgba(255, 255, 255, 0.18);
background: rgba(255, 255, 255, 0.04); background: var(--theme-surface-soft);
} }
.dropzone--active { .dropzone--active {
border-color: rgba(110, 231, 183, 0.6); border-color: rgba(110, 231, 183, 0.6);
@@ -2334,7 +2334,7 @@ onUnmounted(() => {
padding: 10px 8px; padding: 10px 8px;
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.10); border: 1px solid rgba(255, 255, 255, 0.10);
background: rgba(0, 0, 0, 0.18); background: var(--theme-pill-bg);
} }
.poolItem--readonly { .poolItem--readonly {
opacity: 0.58; opacity: 0.58;
@@ -2363,7 +2363,7 @@ onUnmounted(() => {
font-weight: 800; font-weight: 800;
letter-spacing: 0.04em; letter-spacing: 0.04em;
text-transform: uppercase; text-transform: uppercase;
color: rgba(255, 255, 255, 0.58); color: var(--theme-text-soft);
} }
.hidden { .hidden {
display: none; display: none;