diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ac19cf..440bec2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
+## [2.11.2] — 2026-06-04
+
+### Fixed
+- **통계 차트가 빌드(main.exe)에서 안 뜨던 진짜 원인** — frozen 빌드에서 numpy C-확장
+ `numpy.core._multiarray_tests`가 누락(`numpy.testing` 제외의 영향)되어 matplotlib import가
+ `ModuleNotFoundError`로 실패 → "matplotlib 필요" 폴백. `main.spec`에 해당 모듈 hiddenimport
+ 추가 + `numpy.testing` 제외 제거. (디버그 로그로 원인 확인: chart_widget이 실패 사유를 기록)
+- **도전과제 라이트 테마 가독성** — 헤더 강조 숫자/등급 배지/진행 숫자/진행 바를 라이트에서
+ 대비 높은 색으로 조정 (다크는 기존 비비드 색 유지).
+
## [2.11.1] — 2026-06-04
### Fixed
diff --git a/core/version.py b/core/version.py
index 7db5bba..4f4ddc5 100644
--- a/core/version.py
+++ b/core/version.py
@@ -4,4 +4,4 @@
릴리스 시 이 값을 올린 후 git tag → push.
CHANGELOG.md의 최상단 항목과 일치시킬 것.
"""
-__version__ = '2.11.1'
+__version__ = '2.11.2'
diff --git a/main.spec b/main.spec
index 69fd201..45ac162 100644
--- a/main.spec
+++ b/main.spec
@@ -36,11 +36,13 @@ a = Analysis(
'matplotlib.backends.backend_qt5agg',
'PyQt5.QtSvg',
'PyQt5.sip', # matplotlib qt_compat가 sip 사용
+ 'numpy.core._multiarray_tests', # numpy import 체인이 참조 (frozen 차트 깨짐 방지)
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
- excludes=['pandas', 'numpy.testing', 'PyQt5.QtWebEngineWidgets'],
+ # numpy.testing 제외 금지 — numpy.core._multiarray_tests 참조가 끊겨 matplotlib import 실패함
+ excludes=['pandas', 'PyQt5.QtWebEngineWidgets'],
noarchive=False,
optimize=0,
)
diff --git a/ui/achievements_view.py b/ui/achievements_view.py
index 3d4e832..cafb0af 100644
--- a/ui/achievements_view.py
+++ b/ui/achievements_view.py
@@ -165,7 +165,13 @@ class AchievementsView(QDialog):
num_row = QHBoxLayout()
num_row.setSpacing(24)
- big = QLabel(f"{stats['earned']}"
+ # 헤더 강조 숫자색 — 다크는 비비드, 라이트는 동일 색조 진하게(가독성)
+ if _is_dark():
+ c_earned, c_secret, c_pct = '#ffd24a', '#ff90b8', '#4adef0'
+ else:
+ c_earned, c_secret, c_pct = '#C8950A', '#C2185B', '#0E7490'
+
+ big = QLabel(f"{stats['earned']}"
f" / {stats['total']}")
big.setTextFormat(Qt.RichText)
num_row.addWidget(big)
@@ -178,7 +184,7 @@ class AchievementsView(QDialog):
secret_lbl = QLabel(
f"
"
f"🌑 시크릿
"
- f""
+ f""
f"{stats['secret_earned']}"
f" / {stats['secret_total']}"
f"
"
@@ -191,7 +197,7 @@ class AchievementsView(QDialog):
pct_lbl = QLabel(
f""
f"달성률
"
- f""
+ f""
f"{pct:.1f}%
"
)
pct_lbl.setTextFormat(Qt.RichText)
@@ -207,17 +213,17 @@ class AchievementsView(QDialog):
bar.setTextVisible(False)
bar.setMinimumHeight(8)
bar.setMaximumHeight(8)
- bar.setStyleSheet("""
- QProgressBar {
- background: #1a1a26;
+ bar.setStyleSheet(f"""
+ QProgressBar {{
+ background: {tc('panel2')};
border: none;
border-radius: 4px;
- }
- QProgressBar::chunk {
+ }}
+ QProgressBar::chunk {{
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #4adef0, stop:0.5 #6b9eff, stop:1 #ff90b8);
border-radius: 4px;
- }
+ }}
""")
layout.addWidget(bar)
@@ -343,8 +349,8 @@ class AchievementsView(QDialog):
cat_label = QLabel(f" {theme['label']} {theme['name']} · {cat_text} ")
cat_label.setStyleSheet(
f"font-size: 8.5pt; "
- f"color: {theme['border_strong']}; "
- f"background: rgba(255,255,255,0.05); "
+ f"color: {theme['border_strong'] if _is_dark() else tc('text_dim')}; "
+ f"background: {'rgba(255,255,255,0.05)' if _is_dark() else tc('panel2')}; "
f"border: 1px solid {theme['border']}; "
f"border-radius: 8px; "
f"padding: 1px 4px;"
@@ -377,9 +383,9 @@ class AchievementsView(QDialog):
if is_earned:
earned = QLabel(f" ✓ {item['earned_date']} 달성 ")
earned.setStyleSheet(
- f"color: {theme['border_strong']}; "
+ f"color: {theme['border_strong'] if _is_dark() else tc('text')}; "
f"font-weight: bold; font-size: 9.5pt; "
- f"background: rgba(255,255,255,0.08); "
+ f"background: {'rgba(255,255,255,0.08)' if _is_dark() else tc('panel2')}; "
f"border: 1px solid {theme['border']}; "
f"border-radius: 6px; padding: 4px 8px;"
)
@@ -405,7 +411,7 @@ class AchievementsView(QDialog):
pb.setMaximumHeight(10)
pb.setStyleSheet(f"""
QProgressBar {{
- background: rgba(0,0,0,0.4);
+ background: {'rgba(0,0,0,0.4)' if _is_dark() else tc('panel2')};
border: none;
border-radius: 5px;
}}
@@ -419,7 +425,7 @@ class AchievementsView(QDialog):
num = QLabel(f"{progress} / {target}")
num.setStyleSheet(
- f"color: {theme['border_strong']}; font-size: 9pt; "
+ f"color: {theme['border_strong'] if _is_dark() else tc('text_dim')}; font-size: 9pt; "
f"font-weight: bold; background: transparent; border: none;"
)
num.setMinimumWidth(60)