diff --git a/docs/todo.md b/docs/todo.md index 14ccbd2..d542fa2 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,7 +1,7 @@ # 할 일 및 이슈 ## 중기 개선 -- 현재 다크 톤 기준 UI를 유지하되, 다음 단계에서 라이트모드/다크모드 전환 구조를 설계하고 테마 토글을 추가한다. +- 라이트모드/다크모드 1차 전환은 붙였으므로, 관리자 화면과 티어 에디터까지 세부 색상 균형을 더 정교하게 맞추는 후속 테마 보정 작업을 이어간다. - 관리자용 티어표 승인/숨김 처리, 아이템 정렬 UI를 추가한다. - 회원 일괄 작업(다중 선택, 일괄 비밀번호 초기화, 활동 저조 계정 정리) 같은 관리 보조 기능을 추가한다. - 티어 행 프리셋 저장, 색상 관리, 행 복제 같은 고급 편집 기능을 추가한다. diff --git a/docs/update.md b/docs/update.md index fd54f03..a41389b 100644 --- a/docs/update.md +++ b/docs/update.md @@ -1,5 +1,10 @@ # 업데이트 로그 +## 2026-04-01 v1.3.32 +- 전역 테마 변수와 로컬 저장 기반 테마 토글을 추가해, Settings 화면 오른쪽 사이드에서 라이트모드/다크모드를 전환하고 재방문 시 같은 테마를 유지할 수 있게 함. +- 앱 셸, 홈, 게임 허브, 내 티어표, 즐겨찾기, 검색, 로그인, 설정 화면의 공통 카드·입력·텍스트 색을 테마 변수 기준으로 바꿔, 주요 사용자 화면은 라이트/다크 전환이 자연스럽게 이어지도록 1차 정리함. +- 관리자 화면과 티어 에디터처럼 스타일 밀도가 높은 화면은 후속 단계에서 세부 톤을 더 정교하게 맞추도록 todo 기준도 갱신함. + ## 2026-04-01 v1.3.31 - 관리자 게임 관리의 오른쪽 사이드 게임 선택 리스트는 더 많은 항목을 한 번에 볼 수 있도록 최대 높이를 늘리고, 게임 카드 내부 간격도 사용자가 조정한 CSS 기준으로 반영해 목록 밀도를 다시 다듬음. diff --git a/frontend/src/App.vue b/frontend/src/App.vue index b25460e..e092a5f 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -26,6 +26,7 @@ const searchQuery = ref('') const searchPlaceholder = computed(() => (route.name === 'home' ? '게임 템플릿 검색' : '전체 티어표 검색')) const isCollapsedSearchOpen = ref(false) const isGuideModalOpen = ref(false) +const themeMode = ref('dark') const guideStepIndex = ref(0) const viewportWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1440) provide('rightRailOpen', rightRailOpen) @@ -125,6 +126,9 @@ const guideSteps = [ const currentGuideStep = computed(() => guideSteps[guideStepIndex.value] || guideSteps[0]) const isGuidePrevDisabled = computed(() => guideStepIndex.value <= 0) 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 gameHubViewMode = computed(() => (route.query.view === 'list' ? 'list' : 'grid')) const leftBottomPrimaryAction = computed(() => { @@ -240,7 +244,22 @@ function syncViewportWidth() { 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 () => { + 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() if (typeof window !== 'undefined') { syncViewportWidth() @@ -574,7 +593,17 @@ function submitGlobalSearch() {
@@ -607,8 +636,8 @@ function submitGlobalSearch() { min-height: 100dvh; display: grid; grid-template-columns: var(--left-rail-width, 248px) minmax(0, 1fr) var(--right-rail-width, 325px); - background: rgba(14, 14, 14, 0.96); - color: rgba(255, 255, 255, 0.92); + background: var(--theme-shell-bg); + color: var(--theme-text); transition: grid-template-columns 220ms ease; } @@ -619,8 +648,8 @@ function submitGlobalSearch() { .leftRail, .rightRail { min-height: 100dvh; - border-right: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(14, 14, 14, 0.92); + border-right: 1px solid var(--theme-border); + background: var(--theme-rail-bg); box-sizing: border-box; min-width: 0; display: flex; @@ -630,7 +659,7 @@ function submitGlobalSearch() { .rightRail { border-right: 0; - border-left: 1px solid rgba(255, 255, 255, 0.08); + border-left: 1px solid var(--theme-border); transition: opacity 220ms ease, transform 220ms ease, @@ -654,7 +683,7 @@ function submitGlobalSearch() { display: flex; align-items: center; padding: 0 12px; - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid var(--theme-border); box-sizing: border-box; } @@ -713,8 +742,8 @@ function submitGlobalSearch() { height: 28px; padding: 0 10px; border-radius: 8px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.03); + border: 1px solid var(--theme-border); + background: var(--theme-pill-bg); color: rgba(255, 255, 255, 0.72); cursor: pointer; display: inline-flex; @@ -783,7 +812,7 @@ function submitGlobalSearch() { object-fit: cover; flex: 0 0 auto; 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 { @@ -809,7 +838,7 @@ function submitGlobalSearch() { .appUserCard__email { font-size: 12px; - color: rgba(255, 255, 255, 0.56); + color: var(--theme-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -822,8 +851,8 @@ function submitGlobalSearch() { gap: 10px; padding: 11px 12px; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.03); + border: 1px solid var(--theme-border); + background: var(--theme-pill-bg); color: rgba(255, 255, 255, 0.62); margin-bottom: 14px; box-sizing: border-box; @@ -836,7 +865,7 @@ function submitGlobalSearch() { max-width: 100%; border: 0; background: transparent; - color: rgba(255, 255, 255, 0.92); + color: var(--theme-text); outline: none; font: inherit; overflow: hidden; @@ -844,7 +873,7 @@ function submitGlobalSearch() { } .searchStub__input::placeholder { - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); } .searchStub__iconButton { @@ -978,9 +1007,9 @@ function submitGlobalSearch() { gap: 8px; padding: 12px 14px; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(255, 255, 255, 0.05); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-border-strong); + background: var(--theme-surface-soft); + color: var(--theme-text); text-decoration: none; box-sizing: border-box; font-weight: 800; @@ -998,9 +1027,9 @@ function submitGlobalSearch() { min-width: 0; min-height: 0; box-sizing: border-box; - background: rgba(18, 18, 18, 0.98); - border-left: 1px solid rgba(255, 255, 255, 0.08); - border-right: 1px solid rgba(255, 255, 255, 0.08); + background: var(--theme-main-bg); + border-left: 1px solid var(--theme-border); + border-right: 1px solid var(--theme-border); } .appMain--preview { @@ -1045,13 +1074,13 @@ function submitGlobalSearch() { .workspaceHead__brandSub { font-size: 13px; 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: rgba(255, 255, 255, 0.92); + color: var(--theme-text); } .workspaceHead__actions { @@ -1067,7 +1096,7 @@ function submitGlobalSearch() { gap: 6px; padding: 4px; border-radius: 14px; - background: rgba(255, 255, 255, 0.04); + background: var(--theme-surface-soft); } .viewToggle .ghostIcon--iconOnly { @@ -1078,7 +1107,7 @@ function submitGlobalSearch() { } .ghostIcon--active { - background: rgba(255, 255, 255, 0.08); + background: var(--theme-surface-soft-3); } .workspaceBody { @@ -1086,7 +1115,7 @@ function submitGlobalSearch() { padding: 18px 18px 32px; border: 0; border-radius: 0; - background: rgba(24, 24, 24, 0.92); + background: var(--theme-workspace-bg); box-shadow: none; margin: 0; } @@ -1096,7 +1125,7 @@ function submitGlobalSearch() { padding: 18px 18px 32px; border: 0; border-radius: 0; - background: rgba(24, 24, 24, 0.92); + background: var(--theme-workspace-bg); box-shadow: none; margin: 0; } @@ -1118,13 +1147,105 @@ function submitGlobalSearch() { padding-top: 12px; } +.settingsThemePanel { + display: grid; + gap: 10px; + padding: 18px; + border-radius: 22px; + border: 1px solid var(--theme-border); + 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; + align-items: 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; + 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; +} + +.toggleSwitch__thumb { + position: absolute; + 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 { width: 100%; padding: 12px 14px; border-radius: 14px; border: 1px solid rgba(77, 127, 233, 0.96); - background: rgba(77, 127, 233, 0.88); - color: #fff; + background: var(--theme-accent-bg); + color: var(--theme-accent-text); font-weight: 800; cursor: pointer; } @@ -1162,8 +1283,8 @@ function submitGlobalSearch() { align-content: start; gap: 18px; padding: 28px 22px; - background: rgba(255, 255, 255, 0.03); - border-right: 1px solid rgba(255, 255, 255, 0.08); + background: var(--theme-pill-bg); + border-right: 1px solid var(--theme-border); } .guideModal__eyebrow { @@ -1192,7 +1313,7 @@ function submitGlobalSearch() { align-items: center; padding: 12px 14px; 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); color: rgba(255, 255, 255, 0.8); cursor: pointer; @@ -1228,7 +1349,7 @@ function submitGlobalSearch() { justify-self: end; border: 0; background: transparent; - color: rgba(255, 255, 255, 0.56); + color: var(--theme-text-muted); cursor: pointer; font-size: 13px; } @@ -1256,7 +1377,7 @@ function submitGlobalSearch() { width: 100%; aspect-ratio: 16 / 9; 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); display: grid; align-content: center; @@ -1291,7 +1412,7 @@ function submitGlobalSearch() { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); } .guideModal__stepTitle { @@ -1344,8 +1465,8 @@ function submitGlobalSearch() { padding: 12px 18px; border-radius: 14px; border: 1px solid rgba(77, 127, 233, 0.96); - background: rgba(77, 127, 233, 0.88); - color: #fff; + background: var(--theme-accent-bg); + color: var(--theme-accent-text); font-weight: 800; cursor: pointer; } @@ -1354,9 +1475,9 @@ function submitGlobalSearch() { width: 52px; height: 52px; border-radius: 999px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.04); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-border); + background: var(--theme-surface-soft); + color: var(--theme-text); font-size: 28px; line-height: 1; cursor: pointer; @@ -1412,7 +1533,7 @@ function submitGlobalSearch() { flex: 1; border: 0; background: transparent; - color: rgba(255, 255, 255, 0.92); + color: var(--theme-text); font-size: 18px; font-weight: 700; outline: none; @@ -1450,7 +1571,7 @@ function submitGlobalSearch() { justify-content: space-between; padding: 12px 14px; 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); backdrop-filter: blur(12px); box-shadow: 0 14px 30px rgba(0, 0, 0, 0.28); @@ -1484,7 +1605,7 @@ function submitGlobalSearch() { .toast__count { margin-top: 6px; font-size: 12px; - color: rgba(255, 255, 255, 0.56); + color: var(--theme-text-muted); } .toast__close { @@ -1503,7 +1624,7 @@ function submitGlobalSearch() { .guideModal__sidebar { border-right: 0; - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid var(--theme-border); } .guideModal__content { @@ -1530,8 +1651,8 @@ function submitGlobalSearch() { width: min(360px, calc(100vw - 20px)); height: 100dvh; z-index: 30; - border-left: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(14, 14, 14, 0.96); + border-left: 1px solid var(--theme-border); + background: var(--theme-shell-bg); box-shadow: -18px 0 36px rgba(0, 0, 0, 0.34); } @@ -1592,7 +1713,7 @@ function submitGlobalSearch() { min-height: auto; height: auto; border-right: 0; - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid var(--theme-border); } .leftRail__top { diff --git a/frontend/src/style.css b/frontend/src/style.css index d8f8914..d1b6ab4 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -2,12 +2,67 @@ font-family: 'Pretendard', 'Inter', 'Segoe UI', sans-serif; line-height: 1.5; font-weight: 400; - color: rgba(255, 255, 255, 0.92); - background: #121212; + color: var(--theme-text); + background: var(--theme-body-bg); font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -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: var(--theme-text-strong); + --theme-text-muted: var(--theme-text-muted); + --theme-text-soft: var(--theme-text-soft); + --theme-text-faint: rgba(255, 255, 255, 0.4); + --theme-thumb-fallback-bg: #555; + --theme-select-arrow: var(--theme-select-arrow); + --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; +} + +: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: var(--theme-text-strong); + --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; } * { @@ -22,7 +77,9 @@ body, body { margin: 0; - background: #121212; + background: var(--theme-body-bg); + color: var(--theme-text); + transition: background 220ms ease, color 220ms ease; } button, @@ -43,7 +100,7 @@ a { input, select, textarea { - color: rgba(255, 255, 255, 0.92); + color: var(--theme-text); } select { @@ -51,8 +108,8 @@ select { -webkit-appearance: none; -moz-appearance: none; background-image: - linear-gradient(45deg, transparent 50%, rgba(255, 255, 255, 0.72) 50%), - linear-gradient(135deg, rgba(255, 255, 255, 0.72) 50%, transparent 50%); + linear-gradient(45deg, transparent 50%, var(--theme-select-arrow) 50%), + linear-gradient(135deg, var(--theme-select-arrow) 50%, transparent 50%); background-position: calc(100% - 20px) calc(50% - 2px), calc(100% - 14px) calc(50% - 2px); @@ -99,19 +156,19 @@ p { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); } .pageHead__title { font-size: 32px; line-height: 1.05; letter-spacing: -0.04em; - color: rgba(255, 255, 255, 0.96); + color: var(--theme-text-strong); } .pageHead__desc { max-width: 720px; - color: rgba(255, 255, 255, 0.58); + color: var(--theme-text-muted); } .pageHead__aside { diff --git a/frontend/src/views/FavoriteTierListsView.vue b/frontend/src/views/FavoriteTierListsView.vue index ebbe902..da04184 100644 --- a/frontend/src/views/FavoriteTierListsView.vue +++ b/frontend/src/views/FavoriteTierListsView.vue @@ -110,16 +110,16 @@ onMounted(loadFavorites) .select { padding: 11px 13px; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.05); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-border); + background: var(--theme-surface-soft); + color: var(--theme-text); } .btn { padding: 11px 13px; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.06); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-border); + background: var(--theme-surface-soft-2); + color: var(--theme-text); font-weight: 800; cursor: pointer; } @@ -133,18 +133,18 @@ onMounted(loadFavorites) } .boardCard { border-radius: 22px; - border: 1px solid rgba(255, 255, 255, 0.16); - background: rgba(62, 62, 62, 0.82); + border: 1px solid var(--theme-card-border); + background: var(--theme-card-bg); overflow: hidden; 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; } .boardCard:hover { transform: translateY(-2px); - background: rgba(70, 70, 70, 0.96); + background: var(--theme-card-bg-hover); } .boardCard__body { border: 0; @@ -172,10 +172,10 @@ onMounted(loadFavorites) object-fit: cover; } .boardCard__thumbPlaceholder { - background: #555; + background: var(--theme-thumb-fallback-bg); display: grid; place-items: center; - color: rgba(255, 255, 255, 0.4); + color: var(--theme-text-faint); font-size: 13px; font-weight: 700; } @@ -222,7 +222,7 @@ onMounted(loadFavorites) height: 22px; border-radius: 9999px; object-fit: cover; - background: rgba(255, 255, 255, 0.08); + background: var(--theme-border); flex: 0 0 auto; } .boardCard__avatar--fallback { @@ -235,7 +235,7 @@ onMounted(loadFavorites) .favoriteStat { flex: 0 0 auto; font-size: 13px; - color: rgba(255, 255, 255, 0.64); + color: var(--theme-text-faint); white-space: nowrap; } diff --git a/frontend/src/views/GameHubView.vue b/frontend/src/views/GameHubView.vue index d86b535..f6a9462 100644 --- a/frontend/src/views/GameHubView.vue +++ b/frontend/src/views/GameHubView.vue @@ -149,7 +149,7 @@ function submitSearch() { } .dashboardHero__eyebrow { font-size: 12px; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); text-transform: uppercase; letter-spacing: 0.08em; } @@ -157,15 +157,15 @@ function submitSearch() { margin: 4px 0 6px; font-size: 32px; letter-spacing: -0.04em; - color: rgba(255, 255, 255, 0.96); + color: var(--theme-text-strong); } .dashboardHero__desc { margin: 0; - color: rgba(255, 255, 255, 0.58); + color: var(--theme-text-muted); max-width: 720px; } .panel { - /* border: 1px solid rgba(255, 255, 255, 0.08); */ + /* border: 1px solid var(--theme-border); */ background: transparent; border-radius: 0; padding: 0; @@ -174,8 +174,8 @@ function submitSearch() { margin: 10px 0 14px; padding: 10px 12px; border-radius: 12px; - border: 1px solid rgba(239, 68, 68, 0.3); - background: rgba(239, 68, 68, 0.12); + border: 1px solid var(--theme-danger-border); + background: var(--theme-danger-bg); } .panel__title { font-weight: 800; @@ -183,7 +183,7 @@ function submitSearch() { } .panel__sub { margin-top: 6px; - color: rgba(255, 255, 255, 0.56); + color: var(--theme-text-muted); font-size: 13px; } .panel__head { @@ -204,16 +204,16 @@ function submitSearch() { min-width: 240px; padding: 11px 13px; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.05); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-border); + background: var(--theme-surface-soft); + color: var(--theme-text); } .searchBar__button { padding: 11px 14px; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.06); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-border); + background: var(--theme-surface-soft-2); + color: var(--theme-text); font-weight: 800; cursor: pointer; } @@ -232,18 +232,18 @@ function submitSearch() { .boardCard { min-width: 0; border-radius: 22px; - border: 1px solid rgba(255, 255, 255, 0.16); - background: rgba(62, 62, 62, 0.82); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-card-border); + background: var(--theme-card-bg); + color: var(--theme-text); display: grid; 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: transform 0.16s ease, background 0.16s ease; } .boardCard:hover { - background: rgba(70, 70, 70, 0.96); + background: var(--theme-card-bg-hover); transform: translateY(-2px); } .boardCard__body { @@ -293,10 +293,10 @@ function submitSearch() { .boardCard__thumbPlaceholder { width: 100%; height: 100%; - background: #555; + background: var(--theme-thumb-fallback-bg); display: grid; place-items: center; - color: rgba(255, 255, 255, 0.4); + color: var(--theme-text-faint); font-size: 13px; font-weight: 700; border-radius: 18px; @@ -362,7 +362,7 @@ function submitSearch() { border-radius: 9999px; object-fit: cover; border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(255, 255, 255, 0.08); + background: var(--theme-border); flex: 0 0 auto; } .boardCard__avatar--fallback { @@ -377,7 +377,7 @@ function submitSearch() { min-width: 0; max-width: 100%; font-size: 13px; - color: rgba(255, 255, 255, 0.64); + color: var(--theme-text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/frontend/src/views/HomeView.vue b/frontend/src/views/HomeView.vue index 1416b09..be4e0f5 100644 --- a/frontend/src/views/HomeView.vue +++ b/frontend/src/views/HomeView.vue @@ -120,31 +120,31 @@ function thumbUrl(g) { margin: 0 0 16px; padding: 10px 12px; border-radius: 12px; - border: 1px solid rgba(239, 68, 68, 0.18); - background: rgba(239, 68, 68, 0.1); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-danger-border); + background: var(--theme-danger-bg); + color: var(--theme-text); } .pageHead__searchState { margin-top: 8px; - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); } .libraryCard { position: relative; text-align: left; padding: 14px; border-radius: 22px; - border: 1px solid rgba(255, 255, 255, 0.16); - background: rgba(62, 62, 62, 0.82); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-card-border); + background: var(--theme-card-bg); + color: var(--theme-text); cursor: pointer; display: grid; 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; will-change: transform, opacity; } .libraryCard:hover { - background: rgba(70, 70, 70, 0.96); + background: var(--theme-card-bg-hover); transform: translateY(-2px); } .libraryCard__main { @@ -191,8 +191,8 @@ function thumbUrl(g) { width: 100%; aspect-ratio: 16 / 9; border-radius: 14px; - border: 1px solid rgba(255, 255, 255, 0.06); - background: #555; + border: 1px solid var(--theme-surface-soft-2); + background: var(--theme-thumb-fallback-bg); overflow: hidden; display: grid; place-items: center; @@ -204,7 +204,7 @@ function thumbUrl(g) { } .libraryCard__thumbFallback { font-size: 14px; - color: rgba(255, 255, 255, 0.4); + color: var(--theme-text-faint); } .libraryCard__body { display: grid; @@ -241,7 +241,7 @@ function thumbUrl(g) { .libraryEmpty { padding: 20px 0; - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); } @media (max-width: 1400px) { .libraryGrid { diff --git a/frontend/src/views/LoginView.vue b/frontend/src/views/LoginView.vue index cf9abd3..fbea437 100644 --- a/frontend/src/views/LoginView.vue +++ b/frontend/src/views/LoginView.vue @@ -154,7 +154,7 @@ async function submit() { } .authLoading { - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); font-size: 15px; } @@ -164,8 +164,8 @@ async function submit() { width: fit-content; padding: 6px; border-radius: 999px; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(255, 255, 255, 0.03); + border: 1px solid var(--theme-border); + background: var(--theme-pill-bg); } .authTabs__button { @@ -174,14 +174,14 @@ async function submit() { border: 0; border-radius: 999px; background: transparent; - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); font-weight: 700; cursor: pointer; } .authTabs__button--active { background: rgba(76, 133, 245, 0.22); - color: rgba(255, 255, 255, 0.96); + color: var(--theme-text-strong); } .authFields { @@ -196,16 +196,16 @@ async function submit() { .field__label { font-size: 13px; - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); } .field__input { width: 100%; padding: 14px 0; border: 0; - border-bottom: 1px solid rgba(255, 255, 255, 0.12); + border-bottom: 1px solid var(--theme-border-strong); background: transparent; - color: rgba(255, 255, 255, 0.94); + color: var(--theme-text); outline: none; font-size: 18px; letter-spacing: -0.02em; @@ -217,7 +217,7 @@ async function submit() { .field__hint { font-size: 12px; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); } .roleBadge { @@ -226,7 +226,7 @@ async function submit() { border-radius: 999px; border: 1px solid rgba(96, 165, 250, 0.28); background: rgba(96, 165, 250, 0.1); - color: rgba(191, 219, 254, 0.92); + color: var(--theme-text); font-size: 12px; font-weight: 700; } @@ -248,14 +248,14 @@ async function submit() { .primaryAction { border: 1px solid rgba(76, 133, 245, 0.96); - background: rgba(76, 133, 245, 0.92); - color: #fff; + background: var(--theme-accent-bg); + color: var(--theme-accent-text); } .secondaryAction { - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(255, 255, 255, 0.04); - color: rgba(255, 255, 255, 0.86); + border: 1px solid var(--theme-border-strong); + background: var(--theme-surface-soft); + color: var(--theme-text); } @media (max-width: 720px) { diff --git a/frontend/src/views/MyTierListsView.vue b/frontend/src/views/MyTierListsView.vue index e7b4a8b..bf174db 100644 --- a/frontend/src/views/MyTierListsView.vue +++ b/frontend/src/views/MyTierListsView.vue @@ -124,7 +124,7 @@ function openList(t) { } .dashboardHero__eyebrow { font-size: 12px; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); text-transform: uppercase; letter-spacing: 0.08em; } @@ -132,11 +132,11 @@ function openList(t) { margin: 4px 0 6px; font-size: 32px; letter-spacing: -0.04em; - color: rgba(255, 255, 255, 0.96); + color: var(--theme-text-strong); } .dashboardHero__desc { margin: 0; - color: rgba(255, 255, 255, 0.58); + color: var(--theme-text-muted); max-width: 720px; } .panel { @@ -155,18 +155,18 @@ function openList(t) { .boardCard { min-width: 0; border-radius: 22px; - border: 1px solid rgba(255, 255, 255, 0.16); - background: rgba(62, 62, 62, 0.82); - color: rgba(255, 255, 255, 0.92); + border: 1px solid var(--theme-card-border); + background: var(--theme-card-bg); + color: var(--theme-text); 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: transform 0.16s ease, background 0.16s ease; } .boardCard:hover { transform: translateY(-2px); - background: rgba(70, 70, 70, 0.96); + background: var(--theme-card-bg-hover); } .boardCard__body { min-width: 0; @@ -197,10 +197,10 @@ function openList(t) { .boardCard__thumbPlaceholder { width: 100%; height: 100%; - background: #555; + background: var(--theme-thumb-fallback-bg); display: grid; place-items: center; - color: rgba(255, 255, 255, 0.4); + color: var(--theme-text-faint); font-size: 13px; font-weight: 700; border-radius: 18px; @@ -259,7 +259,7 @@ function openList(t) { border-radius: 9999px; object-fit: cover; border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(255, 255, 255, 0.08); + background: var(--theme-border); flex: 0 0 auto; } .boardCard__avatar--fallback { @@ -274,7 +274,7 @@ function openList(t) { min-width: 0; max-width: 100%; font-size: 13px; - color: rgba(255, 255, 255, 0.64); + color: var(--theme-text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/frontend/src/views/ProfileView.vue b/frontend/src/views/ProfileView.vue index de1bf8b..794db15 100644 --- a/frontend/src/views/ProfileView.vue +++ b/frontend/src/views/ProfileView.vue @@ -200,7 +200,7 @@ async function logout() { } .settingsLoading { - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); font-size: 15px; } @@ -221,15 +221,15 @@ async function logout() { position: relative; width: 120px; height: 120px; - border: 1px solid rgba(255, 255, 255, 0.1); + border: 1px solid var(--theme-border-strong); border-radius: 9999px; - background: rgba(255, 255, 255, 0.03); - color: rgba(255, 255, 255, 0.92); + background: var(--theme-pill-bg); + color: var(--theme-text); overflow: hidden; cursor: pointer; display: grid; place-items: center; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); + box-shadow: var(--theme-card-shadow); } .avatarButton__image { @@ -241,7 +241,7 @@ async function logout() { .avatarButton__fallback { font-size: 34px; font-weight: 900; - color: rgba(255, 255, 255, 0.86); + color: var(--theme-text); } .avatarButton__overlay { @@ -251,7 +251,7 @@ async function logout() { background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.72)); font-size: 12px; font-weight: 700; - color: rgba(255, 255, 255, 0.82); + color: var(--theme-text); } .avatarButton__remove { @@ -262,8 +262,8 @@ async function logout() { height: 30px; border: 0; border-radius: 999px; - background: rgba(10, 10, 10, 0.72); - color: rgba(255, 255, 255, 0.88); + background: var(--theme-shell-bg); + color: var(--theme-text); display: grid; place-items: center; cursor: pointer; @@ -283,7 +283,7 @@ async function logout() { .avatarButton__remove:hover { background: rgba(190, 24, 24, 0.88); - color: #fff; + color: var(--theme-accent-text); } .identityMeta { @@ -295,7 +295,7 @@ async function logout() { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; - color: rgba(255, 255, 255, 0.36); + color: var(--theme-text-soft); } .identityMeta__title { @@ -305,7 +305,7 @@ async function logout() { } .identityMeta__desc { - color: rgba(255, 255, 255, 0.58); + color: var(--theme-text-muted); line-height: 1.6; } @@ -326,16 +326,16 @@ async function logout() { .field__label { font-size: 13px; - color: rgba(255, 255, 255, 0.62); + color: var(--theme-text-muted); } .field__input { width: 100%; padding: 14px 0; border: 0; - border-bottom: 1px solid rgba(255, 255, 255, 0.12); + border-bottom: 1px solid var(--theme-border-strong); background: transparent; - color: rgba(255, 255, 255, 0.94); + color: var(--theme-text); outline: none; font-size: 18px; letter-spacing: -0.02em; @@ -346,12 +346,12 @@ async function logout() { } .field__input--readonly { - color: rgba(255, 255, 255, 0.58); + color: var(--theme-text-muted); } .field__hint { font-size: 12px; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); } .roleBadge { @@ -360,7 +360,7 @@ async function logout() { border-radius: 999px; border: 1px solid rgba(96, 165, 250, 0.28); background: rgba(96, 165, 250, 0.1); - color: rgba(191, 219, 254, 0.92); + color: var(--theme-text); font-size: 12px; font-weight: 700; } @@ -382,14 +382,14 @@ async function logout() { .primaryAction { border: 1px solid rgba(76, 133, 245, 0.96); - background: rgba(76, 133, 245, 0.92); - color: #fff; + background: var(--theme-accent-bg); + color: var(--theme-accent-text); } .secondaryAction { - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(255, 255, 255, 0.04); - color: rgba(255, 255, 255, 0.86); + border: 1px solid var(--theme-border-strong); + background: var(--theme-surface-soft); + color: var(--theme-text); } @media (max-width: 720px) { diff --git a/frontend/src/views/SearchResultsView.vue b/frontend/src/views/SearchResultsView.vue index 88fac6b..83726b2 100644 --- a/frontend/src/views/SearchResultsView.vue +++ b/frontend/src/views/SearchResultsView.vue @@ -122,24 +122,24 @@ watch( font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; - color: rgba(255, 255, 255, 0.42); + color: var(--theme-text-soft); } .title { margin: 4px 0 0; font-size: 32px; - color: rgba(255, 255, 255, 0.96); + color: var(--theme-text-strong); letter-spacing: -0.04em; } .desc { margin-top: 6px; - color: rgba(255, 255, 255, 0.58); + color: var(--theme-text-muted); } .error { margin: 0 0 8px; padding: 10px 12px; border-radius: 12px; - border: 1px solid rgba(239, 68, 68, 0.18); - background: rgba(239, 68, 68, 0.1); + border: 1px solid var(--theme-danger-border); + background: var(--theme-danger-bg); } .empty { opacity: 0.76; @@ -151,16 +151,16 @@ watch( } .boardCard { border-radius: 22px; - border: 1px solid rgba(255, 255, 255, 0.16); - background: rgba(62, 62, 62, 0.82); + border: 1px solid var(--theme-card-border); + background: var(--theme-card-bg); overflow: hidden; 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; } .boardCard:hover { transform: translateY(-2px); - background: rgba(70, 70, 70, 0.96); + background: var(--theme-card-bg-hover); } .boardCard__body { border: 0; @@ -188,10 +188,10 @@ watch( object-fit: cover; } .boardCard__thumbPlaceholder { - background: #555; + background: var(--theme-thumb-fallback-bg); display: grid; place-items: center; - color: rgba(255, 255, 255, 0.4); + color: var(--theme-text-faint); font-size: 13px; font-weight: 700; } @@ -238,7 +238,7 @@ watch( height: 22px; border-radius: 9999px; object-fit: cover; - background: rgba(255, 255, 255, 0.08); + background: var(--theme-border); flex: 0 0 auto; } .boardCard__avatar--fallback { @@ -251,7 +251,7 @@ watch( .favoriteStat { flex: 0 0 auto; font-size: 13px; - color: rgba(255, 255, 255, 0.64); + color: var(--theme-text-faint); white-space: nowrap; }