Spaces:
Sleeping
Sleeping
Sync from GitHub Actions
Browse files- CLAUDE.md +1 -0
- docs/superpowers/specs/2026-07-11-model-nav-dropdown-design.md +49 -0
- static/arima.html +1 -31
- static/ets.html +1 -31
- static/hybrid.html +1 -113
- static/index.html +1 -80
- static/lightgbm.html +1 -31
- static/nav.js +98 -0
- static/prophet.html +1 -31
- static/theta.html +1 -31
- static/timesfm.html +1 -81
- static/xgboost.html +1 -31
CLAUDE.md
CHANGED
|
@@ -53,6 +53,7 @@ nbeats/
|
|
| 53 |
├── static/ # 모델별 UI (index=N-BEATS, prophet, arima,
|
| 54 |
│ │ # xgboost, ets, lightgbm, theta,
|
| 55 |
│ ├── hybrid.html # 하이브리드 앙상블, timesfm)
|
|
|
|
| 56 |
│ └── ...
|
| 57 |
├── timesfm-frontend/ # TimesFM 전용 Next.js 앱 (Vercel 배포)
|
| 58 |
├── test_data/ # 테스트용 CSV 데이터셋
|
|
|
|
| 53 |
├── static/ # 모델별 UI (index=N-BEATS, prophet, arima,
|
| 54 |
│ │ # xgboost, ets, lightgbm, theta,
|
| 55 |
│ ├── hybrid.html # 하이브리드 앙상블, timesfm)
|
| 56 |
+
│ ├── nav.js # 공유 모델 드롭다운 내비 (모델 추가 시 MODELS 배열만 수정)
|
| 57 |
│ └── ...
|
| 58 |
├── timesfm-frontend/ # TimesFM 전용 Next.js 앱 (Vercel 배포)
|
| 59 |
├── test_data/ # 테스트용 CSV 데이터셋
|
docs/superpowers/specs/2026-07-11-model-nav-dropdown-design.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 모델 선택 드롭다운 내비게이션 설계
|
| 2 |
+
|
| 3 |
+
날짜: 2026-07-11
|
| 4 |
+
상태: 승인됨 (대화에서 설계 승인 후 기록)
|
| 5 |
+
|
| 6 |
+
## 문제
|
| 7 |
+
|
| 8 |
+
상단 내비가 9개 모델 링크를 한 줄에 담고 `overflow-x: auto`로 처리해,
|
| 9 |
+
화면이 좁으면 옆으로 밀어서(슬라이드) 모델을 찾아야 한다. 사용자가 확인한
|
| 10 |
+
불편: (1) 가로 스크롤로 목록이 잘림, (2) 현재 어떤 모델 페이지인지 파악 어려움.
|
| 11 |
+
또한 동일 내비 마크업+CSS가 9개 HTML에 복붙되어 드리프트가 발생했다
|
| 12 |
+
(예: index.html은 `.tag-classic` CSS 누락).
|
| 13 |
+
|
| 14 |
+
## 결정: 드롭다운 + 공유 스크립트 추출
|
| 15 |
+
|
| 16 |
+
검토한 대안: 드롭다운(채택) / flex-wrap 줄바꿈 내비 / 하이브리드(반응형 전환).
|
| 17 |
+
드롭다운이 두 불편을 모두 해결하고 폭과 무관하게 동작해 채택.
|
| 18 |
+
|
| 19 |
+
### 구조
|
| 20 |
+
|
| 21 |
+
- **`static/nav.js` 신규** — 내비 전체(스타일 주입 + 마크업 생성 + 이벤트)를 담당.
|
| 22 |
+
- 모델 메타데이터(이름·경로·태그·태그 색)는 파일 내 `MODELS` 배열 하나로 관리.
|
| 23 |
+
- `location.pathname`으로 현재 모델을 판별해 버튼 라벨과 목록 강조에 반영.
|
| 24 |
+
- 페이지의 CSS 변수(`--surface`, `--accent` 등)를 사용해 페이지별 테마 유지
|
| 25 |
+
(변수 부재 대비 폴백 값 포함).
|
| 26 |
+
- **9개 HTML 페이지** — 기존 `<nav class="top-nav">` 블록과 내비 전용 CSS
|
| 27 |
+
(`.top-nav`, `.nav-*`, `.model-tag`, `.tag-*`)를 제거하고
|
| 28 |
+
`<script defer src="/static/nav.js"></script>` 한 줄로 대체.
|
| 29 |
+
- 새 모델 추가 시 `MODELS` 배열에 항목 하나만 추가.
|
| 30 |
+
|
| 31 |
+
### 동작
|
| 32 |
+
|
| 33 |
+
- 내비 바: 브랜드("시계열 예측") + 현재 모델명·태그가 표시된 드롭다운 버튼(▾)
|
| 34 |
+
- 버튼 클릭 → 세로 목록(9개, 현재 모델 강조, 카테고리 태그) 토글
|
| 35 |
+
- 닫기: 항목 선택(페이지 이동), 바깥 클릭, Esc(버튼으로 포커스 복귀)
|
| 36 |
+
- 접근성: `aria-haspopup`/`aria-expanded`, 항목은 일반 `<a>`라 Tab/Enter 동작
|
| 37 |
+
- 모바일: 동일 컴포넌트 (가로 스크롤 원천 제거)
|
| 38 |
+
|
| 39 |
+
### 범위 제외
|
| 40 |
+
|
| 41 |
+
- `timesfm-frontend/`(Vercel Next.js)는 별개 앱 — 미변경
|
| 42 |
+
- JS 로드 실패 폴백(noscript) — 로컬 정적 파일이라 생략 (YAGNI)
|
| 43 |
+
|
| 44 |
+
## 테스트
|
| 45 |
+
|
| 46 |
+
- `tests/test_api_contract.py`에 추가: `/static/nav.js` 200 + 모델 목록 포함,
|
| 47 |
+
9개 페이지가 nav.js를 로드하고 인라인 `<nav class="top-nav">`가 없음
|
| 48 |
+
- 실동작: 로컬 기동 후 브라우저에서 드롭다운 열기 → 모델 전환 → 현재 모델
|
| 49 |
+
표시 확인 (`.claude/skills/verify` 레시피)
|
static/arima.html
CHANGED
|
@@ -28,21 +28,6 @@
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
| 31 |
-
.top-nav { background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
|
| 32 |
-
.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 56px; overflow-x: auto; }
|
| 33 |
-
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }
|
| 34 |
-
.nav-links { display: flex; gap: 0.25rem; list-style: none; }
|
| 35 |
-
.nav-links a { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-radius: 8px; text-decoration: none; font-size: 0.82rem; font-weight: 500; color: var(--text-muted); transition: all 0.15s; white-space: nowrap; }
|
| 36 |
-
.nav-links a:hover { color: var(--text); background: var(--surface-hover); }
|
| 37 |
-
.nav-links a.active { color: var(--accent); background: rgba(6, 182, 212, 0.1); }
|
| 38 |
-
.nav-links .model-tag { font-size: 0.6rem; padding: 0.1rem 0.35rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
|
| 39 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 40 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 41 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 42 |
-
.tag-classic { background: rgba(6, 182, 212, 0.15); color: #67e8f9; }
|
| 43 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 44 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 45 |
-
|
| 46 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 47 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 48 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #67e8f9 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
@@ -115,24 +100,9 @@
|
|
| 115 |
.disabled-fields input, .disabled-fields select { opacity: 0.35; }
|
| 116 |
#manualOrderRow input:disabled { cursor: not-allowed; background: var(--surface); }
|
| 117 |
</style>
|
|
|
|
| 118 |
</head>
|
| 119 |
<body>
|
| 120 |
-
<nav class="top-nav">
|
| 121 |
-
<div class="nav-inner">
|
| 122 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 123 |
-
<ul class="nav-links">
|
| 124 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 125 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 126 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 127 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 128 |
-
<li><a href="/arima" class="active">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 129 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 130 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 131 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 132 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 133 |
-
</ul>
|
| 134 |
-
</div>
|
| 135 |
-
</nav>
|
| 136 |
|
| 137 |
<div class="container">
|
| 138 |
<header>
|
|
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 32 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 33 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #67e8f9 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
|
|
| 100 |
.disabled-fields input, .disabled-fields select { opacity: 0.35; }
|
| 101 |
#manualOrderRow input:disabled { cursor: not-allowed; background: var(--surface); }
|
| 102 |
</style>
|
| 103 |
+
<script defer src="/static/nav.js"></script>
|
| 104 |
</head>
|
| 105 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
<div class="container">
|
| 108 |
<header>
|
static/ets.html
CHANGED
|
@@ -28,21 +28,6 @@
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
| 31 |
-
.top-nav { background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
|
| 32 |
-
.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 56px; overflow-x: auto; }
|
| 33 |
-
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }
|
| 34 |
-
.nav-links { display: flex; gap: 0.25rem; list-style: none; }
|
| 35 |
-
.nav-links a { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-radius: 8px; text-decoration: none; font-size: 0.82rem; font-weight: 500; color: var(--text-muted); transition: all 0.15s; white-space: nowrap; }
|
| 36 |
-
.nav-links a:hover { color: var(--text); background: var(--surface-hover); }
|
| 37 |
-
.nav-links a.active { color: var(--accent); background: rgba(16, 185, 129, 0.1); }
|
| 38 |
-
.nav-links .model-tag { font-size: 0.6rem; padding: 0.1rem 0.35rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
|
| 39 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 40 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 41 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 42 |
-
.tag-classic { background: rgba(6, 182, 212, 0.15); color: #67e8f9; }
|
| 43 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 44 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 45 |
-
|
| 46 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 47 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 48 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #6ee7b7 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
@@ -108,24 +93,9 @@
|
|
| 108 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 109 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 110 |
</style>
|
|
|
|
| 111 |
</head>
|
| 112 |
<body>
|
| 113 |
-
<nav class="top-nav">
|
| 114 |
-
<div class="nav-inner">
|
| 115 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 116 |
-
<ul class="nav-links">
|
| 117 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 118 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 119 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 120 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 121 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 122 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 123 |
-
<li><a href="/ets" class="active">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 124 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 125 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 126 |
-
</ul>
|
| 127 |
-
</div>
|
| 128 |
-
</nav>
|
| 129 |
|
| 130 |
<div class="container">
|
| 131 |
<header>
|
|
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 32 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 33 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #6ee7b7 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
|
|
| 93 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 94 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 95 |
</style>
|
| 96 |
+
<script defer src="/static/nav.js"></script>
|
| 97 |
</head>
|
| 98 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
<div class="container">
|
| 101 |
<header>
|
static/hybrid.html
CHANGED
|
@@ -44,103 +44,6 @@
|
|
| 44 |
line-height: 1.6;
|
| 45 |
}
|
| 46 |
|
| 47 |
-
.top-nav {
|
| 48 |
-
background: var(--surface);
|
| 49 |
-
border-bottom: 1px solid var(--border);
|
| 50 |
-
position: sticky;
|
| 51 |
-
top: 0;
|
| 52 |
-
z-index: 100;
|
| 53 |
-
}
|
| 54 |
-
|
| 55 |
-
.nav-inner {
|
| 56 |
-
max-width: 1060px;
|
| 57 |
-
margin: 0 auto;
|
| 58 |
-
padding: 0 2rem;
|
| 59 |
-
display: flex;
|
| 60 |
-
align-items: center;
|
| 61 |
-
gap: 2rem;
|
| 62 |
-
height: 56px;
|
| 63 |
-
overflow-x: auto;
|
| 64 |
-
}
|
| 65 |
-
|
| 66 |
-
.nav-brand {
|
| 67 |
-
font-weight: 700;
|
| 68 |
-
font-size: 1rem;
|
| 69 |
-
color: var(--text);
|
| 70 |
-
text-decoration: none;
|
| 71 |
-
letter-spacing: -0.01em;
|
| 72 |
-
white-space: nowrap;
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
.nav-links {
|
| 76 |
-
display: flex;
|
| 77 |
-
gap: 0.25rem;
|
| 78 |
-
list-style: none;
|
| 79 |
-
}
|
| 80 |
-
|
| 81 |
-
.nav-links a {
|
| 82 |
-
display: flex;
|
| 83 |
-
align-items: center;
|
| 84 |
-
gap: 0.4rem;
|
| 85 |
-
padding: 0.5rem 0.75rem;
|
| 86 |
-
border-radius: 8px;
|
| 87 |
-
text-decoration: none;
|
| 88 |
-
font-size: 0.82rem;
|
| 89 |
-
font-weight: 500;
|
| 90 |
-
color: var(--text-muted);
|
| 91 |
-
transition: all 0.15s;
|
| 92 |
-
white-space: nowrap;
|
| 93 |
-
}
|
| 94 |
-
|
| 95 |
-
.nav-links a:hover {
|
| 96 |
-
color: var(--text);
|
| 97 |
-
background: var(--surface-hover);
|
| 98 |
-
}
|
| 99 |
-
|
| 100 |
-
.nav-links a.active {
|
| 101 |
-
color: var(--accent);
|
| 102 |
-
background: rgba(99, 102, 241, 0.1);
|
| 103 |
-
}
|
| 104 |
-
|
| 105 |
-
.nav-links .model-tag {
|
| 106 |
-
font-size: 0.6rem;
|
| 107 |
-
padding: 0.1rem 0.35rem;
|
| 108 |
-
border-radius: 4px;
|
| 109 |
-
font-weight: 600;
|
| 110 |
-
text-transform: uppercase;
|
| 111 |
-
letter-spacing: 0.03em;
|
| 112 |
-
}
|
| 113 |
-
|
| 114 |
-
.tag-dl {
|
| 115 |
-
background: rgba(99, 102, 241, 0.15);
|
| 116 |
-
color: #a5b4fc;
|
| 117 |
-
}
|
| 118 |
-
|
| 119 |
-
.tag-stat {
|
| 120 |
-
background: rgba(34, 197, 94, 0.15);
|
| 121 |
-
color: #86efac;
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
.tag-ml {
|
| 125 |
-
background: rgba(245, 158, 11, 0.15);
|
| 126 |
-
color: #fcd34d;
|
| 127 |
-
}
|
| 128 |
-
|
| 129 |
-
.tag-classic {
|
| 130 |
-
background: rgba(6, 182, 212, 0.15);
|
| 131 |
-
color: #67e8f9;
|
| 132 |
-
}
|
| 133 |
-
|
| 134 |
-
.tag-ets {
|
| 135 |
-
background: rgba(16, 185, 129, 0.15);
|
| 136 |
-
color: #6ee7b7;
|
| 137 |
-
}
|
| 138 |
-
|
| 139 |
-
.tag-theta {
|
| 140 |
-
background: rgba(168, 85, 247, 0.15);
|
| 141 |
-
color: #c4b5fd;
|
| 142 |
-
}
|
| 143 |
-
|
| 144 |
.tag-hybrid {
|
| 145 |
background: rgba(99, 102, 241, 0.2);
|
| 146 |
color: #a5b4fc;
|
|
@@ -536,25 +439,10 @@
|
|
| 536 |
text-align: left;
|
| 537 |
}
|
| 538 |
</style>
|
|
|
|
| 539 |
</head>
|
| 540 |
|
| 541 |
<body>
|
| 542 |
-
<nav class="top-nav">
|
| 543 |
-
<div class="nav-inner">
|
| 544 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 545 |
-
<ul class="nav-links">
|
| 546 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 547 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 548 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 549 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 550 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 551 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 552 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 553 |
-
<li><a href="/hybrid" class="active">하이브리드 <span class="model-tag tag-hybrid">Hybrid</span></a></li>
|
| 554 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 555 |
-
</ul>
|
| 556 |
-
</div>
|
| 557 |
-
</nav>
|
| 558 |
|
| 559 |
<div class="container">
|
| 560 |
<header>
|
|
|
|
| 44 |
line-height: 1.6;
|
| 45 |
}
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
.tag-hybrid {
|
| 48 |
background: rgba(99, 102, 241, 0.2);
|
| 49 |
color: #a5b4fc;
|
|
|
|
| 439 |
text-align: left;
|
| 440 |
}
|
| 441 |
</style>
|
| 442 |
+
<script defer src="/static/nav.js"></script>
|
| 443 |
</head>
|
| 444 |
|
| 445 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
|
| 447 |
<div class="container">
|
| 448 |
<header>
|
static/index.html
CHANGED
|
@@ -37,70 +37,6 @@
|
|
| 37 |
}
|
| 38 |
|
| 39 |
/* ---- 네비게이션 ---- */
|
| 40 |
-
.top-nav {
|
| 41 |
-
background: var(--surface);
|
| 42 |
-
border-bottom: 1px solid var(--border);
|
| 43 |
-
position: sticky;
|
| 44 |
-
top: 0;
|
| 45 |
-
z-index: 100;
|
| 46 |
-
}
|
| 47 |
-
.nav-inner {
|
| 48 |
-
max-width: 1060px;
|
| 49 |
-
margin: 0 auto;
|
| 50 |
-
padding: 0 2rem;
|
| 51 |
-
display: flex;
|
| 52 |
-
align-items: center;
|
| 53 |
-
gap: 2rem;
|
| 54 |
-
height: 56px;
|
| 55 |
-
overflow-x: auto;
|
| 56 |
-
}
|
| 57 |
-
.nav-brand {
|
| 58 |
-
font-weight: 700;
|
| 59 |
-
font-size: 1rem;
|
| 60 |
-
color: var(--text);
|
| 61 |
-
text-decoration: none;
|
| 62 |
-
letter-spacing: -0.01em;
|
| 63 |
-
white-space: nowrap;
|
| 64 |
-
}
|
| 65 |
-
.nav-links {
|
| 66 |
-
display: flex;
|
| 67 |
-
gap: 0.25rem;
|
| 68 |
-
list-style: none;
|
| 69 |
-
}
|
| 70 |
-
.nav-links a {
|
| 71 |
-
display: flex;
|
| 72 |
-
align-items: center;
|
| 73 |
-
gap: 0.4rem;
|
| 74 |
-
padding: 0.5rem 0.75rem;
|
| 75 |
-
border-radius: 8px;
|
| 76 |
-
text-decoration: none;
|
| 77 |
-
font-size: 0.82rem;
|
| 78 |
-
font-weight: 500;
|
| 79 |
-
white-space: nowrap;
|
| 80 |
-
color: var(--text-muted);
|
| 81 |
-
transition: all 0.15s;
|
| 82 |
-
}
|
| 83 |
-
.nav-links a:hover {
|
| 84 |
-
color: var(--text);
|
| 85 |
-
background: var(--surface-hover);
|
| 86 |
-
}
|
| 87 |
-
.nav-links a.active {
|
| 88 |
-
color: var(--accent);
|
| 89 |
-
background: rgba(99, 102, 241, 0.1);
|
| 90 |
-
}
|
| 91 |
-
.nav-links .model-tag {
|
| 92 |
-
font-size: 0.6rem;
|
| 93 |
-
padding: 0.1rem 0.35rem;
|
| 94 |
-
border-radius: 4px;
|
| 95 |
-
font-weight: 600;
|
| 96 |
-
text-transform: uppercase;
|
| 97 |
-
letter-spacing: 0.03em;
|
| 98 |
-
}
|
| 99 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 100 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 101 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 102 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 103 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 104 |
|
| 105 |
.container {
|
| 106 |
max-width: 1060px;
|
|
@@ -388,24 +324,9 @@
|
|
| 388 |
}
|
| 389 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 390 |
</style>
|
|
|
|
| 391 |
</head>
|
| 392 |
<body>
|
| 393 |
-
<nav class="top-nav">
|
| 394 |
-
<div class="nav-inner">
|
| 395 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 396 |
-
<ul class="nav-links">
|
| 397 |
-
<li><a href="/" class="active">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 398 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 399 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 400 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 401 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 402 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 403 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 404 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 405 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 406 |
-
</ul>
|
| 407 |
-
</div>
|
| 408 |
-
</nav>
|
| 409 |
|
| 410 |
<div class="container">
|
| 411 |
<header>
|
|
|
|
| 37 |
}
|
| 38 |
|
| 39 |
/* ---- 네비게이션 ---- */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
.container {
|
| 42 |
max-width: 1060px;
|
|
|
|
| 324 |
}
|
| 325 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 326 |
</style>
|
| 327 |
+
<script defer src="/static/nav.js"></script>
|
| 328 |
</head>
|
| 329 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 330 |
|
| 331 |
<div class="container">
|
| 332 |
<header>
|
static/lightgbm.html
CHANGED
|
@@ -28,21 +28,6 @@
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
| 31 |
-
.top-nav { background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
|
| 32 |
-
.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 56px; overflow-x: auto; }
|
| 33 |
-
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }
|
| 34 |
-
.nav-links { display: flex; gap: 0.25rem; list-style: none; }
|
| 35 |
-
.nav-links a { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-radius: 8px; text-decoration: none; font-size: 0.82rem; font-weight: 500; color: var(--text-muted); transition: all 0.15s; white-space: nowrap; }
|
| 36 |
-
.nav-links a:hover { color: var(--text); background: var(--surface-hover); }
|
| 37 |
-
.nav-links a.active { color: var(--accent); background: rgba(132, 204, 22, 0.1); }
|
| 38 |
-
.nav-links .model-tag { font-size: 0.6rem; padding: 0.1rem 0.35rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
|
| 39 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 40 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 41 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 42 |
-
.tag-classic { background: rgba(6, 182, 212, 0.15); color: #67e8f9; }
|
| 43 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 44 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 45 |
-
|
| 46 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 47 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 48 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #bef264 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
@@ -106,24 +91,9 @@
|
|
| 106 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 107 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 108 |
</style>
|
|
|
|
| 109 |
</head>
|
| 110 |
<body>
|
| 111 |
-
<nav class="top-nav">
|
| 112 |
-
<div class="nav-inner">
|
| 113 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 114 |
-
<ul class="nav-links">
|
| 115 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 116 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 117 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 118 |
-
<li><a href="/lightgbm" class="active">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 119 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 120 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 121 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 122 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 123 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 124 |
-
</ul>
|
| 125 |
-
</div>
|
| 126 |
-
</nav>
|
| 127 |
|
| 128 |
<div class="container">
|
| 129 |
<header>
|
|
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 32 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 33 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #bef264 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
|
|
| 91 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 92 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 93 |
</style>
|
| 94 |
+
<script defer src="/static/nav.js"></script>
|
| 95 |
</head>
|
| 96 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
<div class="container">
|
| 99 |
<header>
|
static/nav.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* 공유 모델 내비게이션 (드롭다운)
|
| 3 |
+
*
|
| 4 |
+
* 모든 static 페이지가 <script defer src="/static/nav.js">로 로드한다.
|
| 5 |
+
* 모델 추가 시 MODELS 배열에 항목 하나만 추가하면 전 페이지에 반영된다.
|
| 6 |
+
* 색상은 페이지의 CSS 변수(--surface 등)를 사용해 페이지별 테마를 따른다.
|
| 7 |
+
*/
|
| 8 |
+
(function () {
|
| 9 |
+
"use strict";
|
| 10 |
+
|
| 11 |
+
var MODELS = [
|
| 12 |
+
{ path: "/", name: "N-BEATS", tag: "DL", bg: "rgba(99, 102, 241, 0.15)", color: "#a5b4fc" },
|
| 13 |
+
{ path: "/prophet", name: "Prophet", tag: "Stat", bg: "rgba(34, 197, 94, 0.15)", color: "#86efac" },
|
| 14 |
+
{ path: "/xgboost", name: "XGBoost", tag: "ML", bg: "rgba(245, 158, 11, 0.15)", color: "#fcd34d" },
|
| 15 |
+
{ path: "/lightgbm", name: "LightGBM", tag: "ML", bg: "rgba(245, 158, 11, 0.15)", color: "#fcd34d" },
|
| 16 |
+
{ path: "/arima", name: "ARIMA", tag: "Classical", bg: "rgba(6, 182, 212, 0.15)", color: "#67e8f9" },
|
| 17 |
+
{ path: "/theta", name: "Theta", tag: "Classical", bg: "rgba(168, 85, 247, 0.15)", color: "#c4b5fd" },
|
| 18 |
+
{ path: "/ets", name: "ETS", tag: "Smoothing", bg: "rgba(16, 185, 129, 0.15)", color: "#6ee7b7" },
|
| 19 |
+
{ path: "/hybrid", name: "Hybrid", tag: "Ensemble", bg: "rgba(236, 72, 153, 0.15)", color: "#f472b6" },
|
| 20 |
+
{ path: "/timesfm", name: "TimesFM", tag: "FM", bg: "rgba(56, 189, 248, 0.15)", color: "#7dd3fc" }
|
| 21 |
+
];
|
| 22 |
+
|
| 23 |
+
var CSS = [
|
| 24 |
+
'.top-nav { background: var(--surface, #17171c); border-bottom: 1px solid var(--border, #2a2a33); position: sticky; top: 0; z-index: 100; }',
|
| 25 |
+
'.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 1.25rem; height: 56px; }',
|
| 26 |
+
'.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text, #e8e8ed); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }',
|
| 27 |
+
'.model-dd { position: relative; }',
|
| 28 |
+
'.model-dd-btn { display: flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.85rem; border-radius: 8px; border: 1px solid var(--border, #2a2a33); background: transparent; color: var(--text, #e8e8ed); font-size: 0.85rem; font-weight: 600; font-family: inherit; cursor: pointer; transition: border-color 0.15s; }',
|
| 29 |
+
'.model-dd-btn:hover { border-color: var(--accent, #6366f1); }',
|
| 30 |
+
'.model-dd-caret { font-size: 0.65rem; color: var(--text-muted, #9a9aa5); transition: transform 0.15s; }',
|
| 31 |
+
'.model-dd.open .model-dd-caret { transform: rotate(180deg); }',
|
| 32 |
+
'.model-dd-list { position: absolute; top: calc(100% + 6px); left: 0; min-width: 230px; margin: 0; padding: 0.4rem; list-style: none; background: var(--surface, #17171c); border: 1px solid var(--border, #2a2a33); border-radius: 10px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45); z-index: 101; }',
|
| 33 |
+
'.model-dd-list a { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.5rem 0.75rem; border-radius: 7px; text-decoration: none; font-size: 0.85rem; font-weight: 500; color: var(--text-muted, #9a9aa5); }',
|
| 34 |
+
'.model-dd-list a:hover { color: var(--text, #e8e8ed); background: var(--surface-hover, rgba(255, 255, 255, 0.05)); }',
|
| 35 |
+
'.model-dd-list a.active { color: var(--accent, #6366f1); background: rgba(99, 102, 241, 0.1); }',
|
| 36 |
+
'.model-tag { font-size: 0.6rem; padding: 0.12rem 0.4rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }'
|
| 37 |
+
].join('\n');
|
| 38 |
+
|
| 39 |
+
function tagHtml(model) {
|
| 40 |
+
return '<span class="model-tag" style="background:' + model.bg + ';color:' + model.color + ';">' + model.tag + '</span>';
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
function normalizePath(p) {
|
| 44 |
+
return p.length > 1 && p.slice(-1) === '/' ? p.slice(0, -1) : p;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
var currentPath = normalizePath(window.location.pathname);
|
| 48 |
+
var current = MODELS.filter(function (m) { return m.path === currentPath; })[0] || MODELS[0];
|
| 49 |
+
|
| 50 |
+
var items = MODELS.map(function (m) {
|
| 51 |
+
var active = m.path === current.path ? ' class="active"' : '';
|
| 52 |
+
return '<li><a href="' + m.path + '"' + active + '><span>' + m.name + '</span>' + tagHtml(m) + '</a></li>';
|
| 53 |
+
}).join('');
|
| 54 |
+
|
| 55 |
+
var style = document.createElement('style');
|
| 56 |
+
style.textContent = CSS;
|
| 57 |
+
document.head.appendChild(style);
|
| 58 |
+
|
| 59 |
+
var nav = document.createElement('nav');
|
| 60 |
+
nav.className = 'top-nav';
|
| 61 |
+
nav.innerHTML =
|
| 62 |
+
'<div class="nav-inner">' +
|
| 63 |
+
'<a href="/" class="nav-brand">시계열 예측</a>' +
|
| 64 |
+
'<div class="model-dd">' +
|
| 65 |
+
'<button type="button" class="model-dd-btn" aria-haspopup="true" aria-expanded="false">' +
|
| 66 |
+
'<span>' + current.name + '</span>' + tagHtml(current) +
|
| 67 |
+
'<span class="model-dd-caret">▾</span>' +
|
| 68 |
+
'</button>' +
|
| 69 |
+
'<ul class="model-dd-list" hidden>' + items + '</ul>' +
|
| 70 |
+
'</div>' +
|
| 71 |
+
'</div>';
|
| 72 |
+
document.body.insertAdjacentElement('afterbegin', nav);
|
| 73 |
+
|
| 74 |
+
var dd = nav.querySelector('.model-dd');
|
| 75 |
+
var btn = nav.querySelector('.model-dd-btn');
|
| 76 |
+
var list = nav.querySelector('.model-dd-list');
|
| 77 |
+
|
| 78 |
+
function setOpen(open) {
|
| 79 |
+
list.hidden = !open;
|
| 80 |
+
dd.classList.toggle('open', open);
|
| 81 |
+
btn.setAttribute('aria-expanded', String(open));
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
btn.addEventListener('click', function () {
|
| 85 |
+
setOpen(list.hidden);
|
| 86 |
+
});
|
| 87 |
+
|
| 88 |
+
document.addEventListener('click', function (e) {
|
| 89 |
+
if (!list.hidden && !dd.contains(e.target)) setOpen(false);
|
| 90 |
+
});
|
| 91 |
+
|
| 92 |
+
document.addEventListener('keydown', function (e) {
|
| 93 |
+
if (e.key === 'Escape' && !list.hidden) {
|
| 94 |
+
setOpen(false);
|
| 95 |
+
btn.focus();
|
| 96 |
+
}
|
| 97 |
+
});
|
| 98 |
+
})();
|
static/prophet.html
CHANGED
|
@@ -28,21 +28,6 @@
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
| 31 |
-
.top-nav { background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
|
| 32 |
-
.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 56px; overflow-x: auto; }
|
| 33 |
-
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }
|
| 34 |
-
.nav-links { display: flex; gap: 0.25rem; list-style: none; }
|
| 35 |
-
.nav-links a { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-radius: 8px; text-decoration: none; font-size: 0.82rem; font-weight: 500; color: var(--text-muted); transition: all 0.15s; white-space: nowrap; }
|
| 36 |
-
.nav-links a:hover { color: var(--text); background: var(--surface-hover); }
|
| 37 |
-
.nav-links a.active { color: var(--accent); background: rgba(34, 197, 94, 0.1); }
|
| 38 |
-
.nav-links .model-tag { font-size: 0.6rem; padding: 0.1rem 0.35rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
|
| 39 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 40 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 41 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 42 |
-
.tag-classic { background: rgba(6, 182, 212, 0.15); color: #67e8f9; }
|
| 43 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 44 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 45 |
-
|
| 46 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 47 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 48 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #86efac 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
@@ -106,24 +91,9 @@
|
|
| 106 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 107 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 108 |
</style>
|
|
|
|
| 109 |
</head>
|
| 110 |
<body>
|
| 111 |
-
<nav class="top-nav">
|
| 112 |
-
<div class="nav-inner">
|
| 113 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 114 |
-
<ul class="nav-links">
|
| 115 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 116 |
-
<li><a href="/prophet" class="active">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 117 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 118 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 119 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 120 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 121 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 122 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 123 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 124 |
-
</ul>
|
| 125 |
-
</div>
|
| 126 |
-
</nav>
|
| 127 |
|
| 128 |
<div class="container">
|
| 129 |
<header>
|
|
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 32 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 33 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #86efac 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
|
|
| 91 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 92 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 93 |
</style>
|
| 94 |
+
<script defer src="/static/nav.js"></script>
|
| 95 |
</head>
|
| 96 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
<div class="container">
|
| 99 |
<header>
|
static/theta.html
CHANGED
|
@@ -28,21 +28,6 @@
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
| 31 |
-
.top-nav { background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
|
| 32 |
-
.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 56px; overflow-x: auto; }
|
| 33 |
-
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }
|
| 34 |
-
.nav-links { display: flex; gap: 0.25rem; list-style: none; }
|
| 35 |
-
.nav-links a { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-radius: 8px; text-decoration: none; font-size: 0.82rem; font-weight: 500; color: var(--text-muted); transition: all 0.15s; white-space: nowrap; }
|
| 36 |
-
.nav-links a:hover { color: var(--text); background: var(--surface-hover); }
|
| 37 |
-
.nav-links a.active { color: var(--accent); background: rgba(168, 85, 247, 0.1); }
|
| 38 |
-
.nav-links .model-tag { font-size: 0.6rem; padding: 0.1rem 0.35rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
|
| 39 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 40 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 41 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 42 |
-
.tag-classic { background: rgba(6, 182, 212, 0.15); color: #67e8f9; }
|
| 43 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 44 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 45 |
-
|
| 46 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 47 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 48 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #c4b5fd 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
@@ -108,24 +93,9 @@
|
|
| 108 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 109 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 110 |
</style>
|
|
|
|
| 111 |
</head>
|
| 112 |
<body>
|
| 113 |
-
<nav class="top-nav">
|
| 114 |
-
<div class="nav-inner">
|
| 115 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 116 |
-
<ul class="nav-links">
|
| 117 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 118 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 119 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 120 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 121 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 122 |
-
<li><a href="/theta" class="active">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 123 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 124 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 125 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 126 |
-
</ul>
|
| 127 |
-
</div>
|
| 128 |
-
</nav>
|
| 129 |
|
| 130 |
<div class="container">
|
| 131 |
<header>
|
|
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 32 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 33 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #c4b5fd 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
|
|
| 93 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 94 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 95 |
</style>
|
| 96 |
+
<script defer src="/static/nav.js"></script>
|
| 97 |
</head>
|
| 98 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
<div class="container">
|
| 101 |
<header>
|
static/timesfm.html
CHANGED
|
@@ -38,70 +38,6 @@
|
|
| 38 |
}
|
| 39 |
|
| 40 |
/* ---- 네비게이션 ---- */
|
| 41 |
-
.top-nav {
|
| 42 |
-
background: var(--surface);
|
| 43 |
-
border-bottom: 1px solid var(--border);
|
| 44 |
-
position: sticky;
|
| 45 |
-
top: 0;
|
| 46 |
-
z-index: 100;
|
| 47 |
-
}
|
| 48 |
-
.nav-inner {
|
| 49 |
-
max-width: 1060px;
|
| 50 |
-
margin: 0 auto;
|
| 51 |
-
padding: 0 2rem;
|
| 52 |
-
display: flex;
|
| 53 |
-
align-items: center;
|
| 54 |
-
gap: 2rem;
|
| 55 |
-
height: 56px;
|
| 56 |
-
overflow-x: auto;
|
| 57 |
-
}
|
| 58 |
-
.nav-brand {
|
| 59 |
-
font-weight: 700;
|
| 60 |
-
font-size: 1rem;
|
| 61 |
-
color: var(--text);
|
| 62 |
-
text-decoration: none;
|
| 63 |
-
letter-spacing: -0.01em;
|
| 64 |
-
white-space: nowrap;
|
| 65 |
-
}
|
| 66 |
-
.nav-links {
|
| 67 |
-
display: flex;
|
| 68 |
-
gap: 0.25rem;
|
| 69 |
-
list-style: none;
|
| 70 |
-
}
|
| 71 |
-
.nav-links a {
|
| 72 |
-
display: flex;
|
| 73 |
-
align-items: center;
|
| 74 |
-
gap: 0.4rem;
|
| 75 |
-
padding: 0.5rem 0.75rem;
|
| 76 |
-
border-radius: 8px;
|
| 77 |
-
text-decoration: none;
|
| 78 |
-
font-size: 0.82rem;
|
| 79 |
-
font-weight: 500;
|
| 80 |
-
white-space: nowrap;
|
| 81 |
-
color: var(--text-muted);
|
| 82 |
-
transition: all 0.15s;
|
| 83 |
-
}
|
| 84 |
-
.nav-links a:hover {
|
| 85 |
-
color: var(--text);
|
| 86 |
-
background: var(--surface-hover);
|
| 87 |
-
}
|
| 88 |
-
.nav-links a.active {
|
| 89 |
-
color: var(--sky);
|
| 90 |
-
background: rgba(56, 189, 248, 0.1);
|
| 91 |
-
}
|
| 92 |
-
.nav-links .model-tag {
|
| 93 |
-
font-size: 0.6rem;
|
| 94 |
-
padding: 0.1rem 0.35rem;
|
| 95 |
-
border-radius: 4px;
|
| 96 |
-
font-weight: 600;
|
| 97 |
-
text-transform: uppercase;
|
| 98 |
-
letter-spacing: 0.03em;
|
| 99 |
-
}
|
| 100 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 101 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 102 |
-
.tag-theta{ background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 103 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 104 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 105 |
.tag-fm { background: rgba(56, 189, 248, 0.15); color: #7dd3fc; }
|
| 106 |
|
| 107 |
.container {
|
|
@@ -333,26 +269,10 @@
|
|
| 333 |
.result-table tr:hover td { background: rgba(255,255,255,0.02); }
|
| 334 |
.row-future td:first-child { color: var(--sky); }
|
| 335 |
</style>
|
|
|
|
| 336 |
</head>
|
| 337 |
<body>
|
| 338 |
|
| 339 |
-
<nav class="top-nav">
|
| 340 |
-
<div class="nav-inner">
|
| 341 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 342 |
-
<ul class="nav-links">
|
| 343 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 344 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 345 |
-
<li><a href="/xgboost">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 346 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 347 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-stat">Classical</span></a></li>
|
| 348 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 349 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 350 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background:rgba(236,72,153,0.15);color:#f472b6;">Ensemble</span></a></li>
|
| 351 |
-
<li><a href="/timesfm" class="active">TimesFM <span class="model-tag tag-fm">FM</span></a></li>
|
| 352 |
-
</ul>
|
| 353 |
-
</div>
|
| 354 |
-
</nav>
|
| 355 |
-
|
| 356 |
<div class="container">
|
| 357 |
<header>
|
| 358 |
<div>
|
|
|
|
| 38 |
}
|
| 39 |
|
| 40 |
/* ---- 네비게이션 ---- */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
.tag-fm { background: rgba(56, 189, 248, 0.15); color: #7dd3fc; }
|
| 42 |
|
| 43 |
.container {
|
|
|
|
| 269 |
.result-table tr:hover td { background: rgba(255,255,255,0.02); }
|
| 270 |
.row-future td:first-child { color: var(--sky); }
|
| 271 |
</style>
|
| 272 |
+
<script defer src="/static/nav.js"></script>
|
| 273 |
</head>
|
| 274 |
<body>
|
| 275 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
<div class="container">
|
| 277 |
<header>
|
| 278 |
<div>
|
static/xgboost.html
CHANGED
|
@@ -28,21 +28,6 @@
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
| 31 |
-
.top-nav { background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
|
| 32 |
-
.nav-inner { max-width: 1060px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 56px; overflow-x: auto; }
|
| 33 |
-
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); text-decoration: none; letter-spacing: -0.01em; white-space: nowrap; }
|
| 34 |
-
.nav-links { display: flex; gap: 0.25rem; list-style: none; }
|
| 35 |
-
.nav-links a { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-radius: 8px; text-decoration: none; font-size: 0.82rem; font-weight: 500; color: var(--text-muted); transition: all 0.15s; white-space: nowrap; }
|
| 36 |
-
.nav-links a:hover { color: var(--text); background: var(--surface-hover); }
|
| 37 |
-
.nav-links a.active { color: var(--accent); background: rgba(245, 158, 11, 0.1); }
|
| 38 |
-
.nav-links .model-tag { font-size: 0.6rem; padding: 0.1rem 0.35rem; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
|
| 39 |
-
.tag-dl { background: rgba(99, 102, 241, 0.15); color: #a5b4fc; }
|
| 40 |
-
.tag-stat { background: rgba(34, 197, 94, 0.15); color: #86efac; }
|
| 41 |
-
.tag-ml { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
|
| 42 |
-
.tag-classic { background: rgba(6, 182, 212, 0.15); color: #67e8f9; }
|
| 43 |
-
.tag-ets { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
|
| 44 |
-
.tag-theta { background: rgba(168, 85, 247, 0.15); color: #c4b5fd; }
|
| 45 |
-
|
| 46 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 47 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 48 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #fcd34d 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
@@ -106,24 +91,9 @@
|
|
| 106 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 107 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 108 |
</style>
|
|
|
|
| 109 |
</head>
|
| 110 |
<body>
|
| 111 |
-
<nav class="top-nav">
|
| 112 |
-
<div class="nav-inner">
|
| 113 |
-
<a href="/" class="nav-brand">시계열 예측</a>
|
| 114 |
-
<ul class="nav-links">
|
| 115 |
-
<li><a href="/">N-BEATS <span class="model-tag tag-dl">DL</span></a></li>
|
| 116 |
-
<li><a href="/prophet">Prophet <span class="model-tag tag-stat">Stat</span></a></li>
|
| 117 |
-
<li><a href="/xgboost" class="active">XGBoost <span class="model-tag tag-ml">ML</span></a></li>
|
| 118 |
-
<li><a href="/lightgbm">LightGBM <span class="model-tag tag-ml">ML</span></a></li>
|
| 119 |
-
<li><a href="/arima">ARIMA <span class="model-tag tag-classic">Classical</span></a></li>
|
| 120 |
-
<li><a href="/theta">Theta <span class="model-tag tag-theta">Classical</span></a></li>
|
| 121 |
-
<li><a href="/ets">ETS <span class="model-tag tag-ets">Smoothing</span></a></li>
|
| 122 |
-
<li><a href="/hybrid">Hybrid <span class="model-tag" style="background: rgba(236, 72, 153, 0.15); color: #f472b6;">Ensemble</span></a></li>
|
| 123 |
-
<li><a href="/timesfm">TimesFM <span class="model-tag" style="background: rgba(56, 189, 248, 0.15); color: #7dd3fc;">FM</span></a></li>
|
| 124 |
-
</ul>
|
| 125 |
-
</div>
|
| 126 |
-
</nav>
|
| 127 |
|
| 128 |
<div class="container">
|
| 129 |
<header>
|
|
|
|
| 28 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 29 |
body { font-family: 'Outfit', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; line-height: 1.6; }
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
.container { max-width: 1060px; margin: 0 auto; padding: 2rem; }
|
| 32 |
header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
|
| 33 |
h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #fff 0%, #fcd34d 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
|
|
|
| 91 |
.spinner { display: inline-block; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: -0.15em; margin-right: 0.4em; }
|
| 92 |
@keyframes spin { to { transform: rotate(360deg); } }
|
| 93 |
</style>
|
| 94 |
+
<script defer src="/static/nav.js"></script>
|
| 95 |
</head>
|
| 96 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
<div class="container">
|
| 99 |
<header>
|