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() {
-
+
+ Appearance
+ 테마 설정
+ 밝은 톤과 어두운 톤 중 원하는 작업 환경으로 전환할 수 있어요.
+
+
+
@@ -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;
}