Public Source Viewer
비나래아카이브 개발자 포털
실제 서비스 구조를 살펴볼 수 있는 공개용 코드 뷰어입니다. 인증, 세션, 외부 연동, 토큰, 관리자 식별 등 보안상 민감한 구현은 파일 단위 또는 줄 단위로 검열됩니다.
view/hinana/lounge.ejs
공개 가능
1
<!DOCTYPE html>
2
<html lang="ko" xmlns="http://www.w3.org/1999/xhtml">
3
<head>
4
<meta charset="utf-8" />
5
<meta name="color-scheme" content="light dark">
6
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, maximum-scale=1.0">
7
<link rel="manifest" href="/manifest.json">
8
<meta name="theme-color" content="<%= (typeof theme !== 'undefined' && theme === 'dark') ? '#0f141e' : '#f8f7f5' %>">
9
<meta name="apple-mobile-web-app-title" content="비나래 라운지">
10
<meta property="og:image" content="/image/train_hinana.png" />
11
<meta property="og:description" content="비나래 라운지"/>
12
<meta property="og:url" content="hinana.moe/hinana/lounge"/>
13
<meta property="og:title" content="비나래 라운지"/>
14
<title>비나래 라운지</title>
15
16
<link rel='stylesheet' href='/vendors/bootstrap/css/bootstrap.min.css' />
17
<script src="/vendors/bootstrap/js/bootstrap.min.js"></script>
18
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css">
19
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet" type="text/css">
20
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
21
22
<style>
23
:root {
24
--font-family: 'Noto Sans KR', sans-serif;
25
--bg-main: #f8f7f5; --bg-secondary: #ffffff; --bg-tertiary: #1a2238;
26
--text-primary: #1a2238; --text-secondary: #5e6676;
27
--accent-color: #c5a059; --danger-color: #dc2626; --border-color: #e5e1da;
28
--shadow-md: 0 10px 40px -10px rgba(26, 34, 56, 0.12);
29
--shadow-sm: 0 2px 8px rgba(0,0,0,0.05);
30
}
31
32
body.dark-mode {
33
--bg-main: #0f141e; --bg-secondary: #1a2238; --bg-tertiary: #0a0e17;
34
--text-primary: #e7e5e4; --text-secondary: #a8a29e;
35
--accent-color: #d4b47a; --border-color: #2e3a59;
36
}
37
38
html, body {
39
height: auto !important; min-height: 100%; margin: 0; padding: 0;
40
font-family: var(--font-family); background-color: var(--bg-main); color: var(--text-primary);
41
overflow-x: hidden; overflow-y: auto; width: 100%;
42
}
43
44
a { text-decoration: none; color: inherit; }
45
46
/* [Header] */
47
.global-header {
48
height: 60px; background-color: var(--bg-tertiary); border-bottom: 1px solid var(--border-color);
49
display: flex; align-items: center; justify-content: space-between; padding: 0 40px;
50
position: sticky; top: 0; z-index: 1000; color: white; flex-wrap: wrap;
51
}
52
.header-logo { height: 32px; }
53
body:not(.dark-mode) .logo-night { display: none; }
54
body.dark-mode .logo-day { display: none; }
55
.header-brand { display: flex; align-items: center; flex: 0 0 auto; }
56
.header-nav { display: flex; gap: 20px; align-items: center; transition: all 0.3s ease; }
57
58
/* [Layout] */
59
.layout-container {
60
display: flex;
61
min-height: calc(100vh - 60px);
62
background-color: var(--bg-main);
63
width: 100%; max-width: 100vw; overflow-x: hidden;
64
}
65
66
/* [Content Column] */
67
.content-column {
68
flex: 1; padding: 60px 40px;
69
display: flex; flex-direction: column; align-items: center;
70
width: 100%; min-width: 0;
71
}
72
73
.lounge-hero { text-align: center; margin-bottom: 50px; }
74
.info-title { font-size: 2.8rem; font-weight: 700; color: var(--text-primary); margin: 15px 0; letter-spacing: -1px; }
75
76
.effect-box { position: relative; height: 300px; width: 100%; max-width: 500px; display: flex; justify-content: center; align-items: center; margin-bottom: 30px; }
77
.effect-box img {
78
position: absolute; width: 100%; height: 240px;
79
object-fit: cover; border: 1px solid var(--accent-color); border-radius: 2px;
80
box-shadow: var(--shadow-md);
81
}
82
83
.luxury-card {
84
width: 100%; max-width: 800px; background-color: var(--bg-secondary);
85
padding: 40px; border-radius: 4px; border: 1px solid var(--border-color);
86
border-top: 5px solid var(--accent-color) !important; box-shadow: var(--shadow-md);
87
}
88
89
.service-btn {
90
display: block; text-align: center; padding: 25px;
91
border: 1px solid var(--border-color); border-radius: 4px;
92
background-color: var(--bg-main); transition: all 0.2s;
93
color: var(--text-primary);
94
text-decoration: none;
95
}
96
.service-btn:hover {
97
transform: translateY(-5px);
98
border-color: var(--accent-color);
99
box-shadow: var(--shadow-md);
100
color: var(--accent-color);
101
}
102
103
/* [Right Sidebar] */
104
.info-column {
105
flex: 0 0 320px;
106
width: 320px;
107
background-color: var(--bg-secondary);
108
border-left: 1px solid var(--border-color);
109
padding: 40px 0;
110
display: flex; flex-direction: column; align-items: center;
111
}
112
113
.info-card {
114
width: 270px;
115
background-color: var(--bg-main);
116
border: 1px solid var(--border-color);
117
border-radius: 12px;
118
padding: 24px 20px;
119
margin-bottom: 20px;
120
box-shadow: var(--shadow-sm);
121
}
122
123
/* [Responsive] */
124
@media (max-width: 1200px) {
125
.global-header { padding: 10px 20px; }
126
.layout-container { flex-direction: column; align-items: center; }
127
.content-column { width: 100%; padding: 40px 20px; }
128
129
.info-column {
130
width: 100%; flex: auto;
131
border-left: none; border-top: 1px solid var(--border-color);
132
padding: 40px 20px;
133
}
134
.info-card { width: 100%; }
135
.info-column > div:last-child { margin-bottom: 60px; }
136
}
137
138
@media (max-width: 991px) {
139
.global-header { height: auto; min-height: 60px; padding: 10px 15px; }
140
.header-brand { order: 1; }
141
.header-nav { gap: 15px !important; order: 2; margin-left: auto; }
142
.header-controls {
143
width: 100%; order: 3; display: flex; justify-content: flex-end;
144
margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.15);
145
}
146
}
147
.verified-badge { color: #1d9bf0; font-size: 0.85em; margin-left: 2px; }
148
.verified-badge-admin { color: var(--accent-color); font-size: 0.85em; margin-left: 2px; }
149
150
.service-btn span {
151
display: -webkit-box;
152
-webkit-line-clamp: 2;
153
line-clamp: 2;
154
-webkit-box-orient: vertical;
155
overflow: hidden;
156
min-height: 2.8em;
157
display: flex;
158
align-items: center;
159
justify-content: center;
160
line-height: 1.2;
161
}
162
</style>
163
</head>
164
165
<body class="<%= (typeof theme !== 'undefined' && theme === 'dark') ? 'dark-mode' : '' %>">
166
<header class="global-header">
167
<div class="header-brand">
168
<a href="/hinana/lounge">
169
<img src="/image/lounge1.png" alt="비나래 라운지" class="header-logo">
170
</a>
171
</div>
172
<nav class="header-nav">
173
<a href="/hinana/index" class="nav-link text-white-50 small fw-bold">Archive</a>
174
<a href="/hinana/lounge" class="nav-link text-white fw-bold">Lounge</a>
175
<a href="/hinana/gallery" class="nav-link text-white-50 small fw-bold">Gallery</a>
176
</nav>
177
<div class="header-controls" style="display:flex; align-items:center; gap:12px;">
178
<a href="/hinana/gallery#brand-assets" class="text-white-50 small fw-bold" style="text-decoration:none;">사이트 맵</a>
179
<form action="/toggle-theme" method="POST" style="margin:0;">
180
<button type="submit" class="btn text-white p-1"><i class="bi bi-moon-stars"></i></button>
181
</form>
182
</div>
183
</header>
184
185
<div class="layout-container">
186
<div class="content-column">
187
<div class="lounge-hero">
188
<span style="color: var(--accent-color); letter-spacing: 5px; font-weight: bold; font-size: 0.8rem;">ESTABLISHED 2026</span>
189
<h2 class="info-title">비나래 라운지</h2>
190
<div style="width: 60px; height: 1px; background: var(--accent-color); margin: 0 auto;"></div>
191
</div>
192
193
<div class="effect-box">
194
<img src="/image/<%= randomLoungeImage %>" style="transform: rotate(-6deg) scale(0.9); opacity: 0.3;">
195
<img src="/image/<%= randomLoungeImage %>" style="transform: rotate(-3deg) scale(0.95); opacity: 0.6;">
196
<img src="/image/<%= randomLoungeImage %>" style="z-index: 3;">
197
</div>
198
199
<div class="text-center mb-5" style="max-width: 600px;">
200
<h4 class="fw-light mb-3" style="color: var(--accent-color)">고요한 아카이브와 라운지의 만남</h4>
201
<p class="text-secondary">아카이브를 나와 라운지로. 히나나와 함께.</p>
202
</div>
203
204
<div class="luxury-card">
205
<div class="row g-4 justify-content-center">
206
207
<div class="col-6 col-md-3">
208
<a href="/hinana/gallery" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
209
<i class="bi bi-palette fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
210
<span class="fw-bold small">라운지 갤러리</span>
211
</a>
212
</div>
213
214
<div class="col-6 col-md-3">
215
<a href="/hinana/plaza" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
216
<i class="bi bi-chat-dots fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
217
<span class="fw-bold small">비나래 광장</span>
218
</a>
219
</div>
220
221
<div class="col-6 col-md-3">
222
<a href="/hinana/tetris" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
223
<i class="bi bi-controller fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
224
<span class="fw-bold small">TETRIS</span>
225
</a>
226
</div>
227
228
<div class="col-6 col-md-3">
229
<a href="/hinana/train" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
230
<i class="bi bi-train-front fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
231
<span class="fw-bold small">특급 히나나호</span>
232
</a>
233
</div>
234
235
<div class="col-6 col-md-3">
236
<a href="/hinana/shop" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
237
<i class="bi bi-bookmark-star fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
238
<span class="fw-bold small">책갈피 교환소</span>
239
</a>
240
</div>
241
242
<div class="col-6 col-md-3">
243
<a href="/hinana/image" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
244
<i class="bi bi-image fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
245
<span class="fw-bold small">이미지 편집기</span>
246
</a>
247
</div>
248
<div class="col-6 col-md-3">
249
<a href="/hinana/exhibition" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
250
<i class="bi bi-easel2 fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
251
<span class="fw-bold small">특별전</span>
252
<span style="font-size:0.65rem; color:var(--text-secondary); margin-top:2px;">Claude Design 테스트</span>
253
</a>
254
</div>
255
<div class="col-6 col-md-3">
256
<a href="/hinana/echo" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
257
<i class="bi bi-soundwave fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
258
<span class="fw-bold small">에코 스튜디오</span>
259
</a>
260
</div>
261
<div class="col-6 col-md-3">
262
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
263
<i class="bi bi-calculator fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
264
<span class="fw-bold small">AI 토큰 계산기</span>
265
</a>
266
</div>
267
<div class="col-6 col-md-3">
268
<a href="/hinana/subway" class="service-btn h-100 d-flex flex-column justify-content-center align-items-center">
269
<i class="bi bi-train-front fs-2 mb-2 d-block" style="color: var(--accent-color)"></i>
270
<span class="fw-bold small">열차 위치 조회</span>
271
</a>
272
</div>
273
</div>
274
</div>
275
</div>
276
277
<div class="info-column">
278
<div class="info-card text-center">
279
<div style="font-size: 0.65rem; color: var(--accent-color); letter-spacing: 3px; font-weight: 700; margin-bottom: 20px;">PASSENGER INFO</div>
280
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
281
282
<div>
283
<% if(username) { %>
284
<a href="/logout?redirect=/hinana/lounge" class="btn btn-outline-dark btn-sm w-100 py-2" style="letter-spacing: 1px;">SIGN OUT</a>
285
<% } else { %>
286
<a href="/login?redirect=/hinana/lounge" class="btn btn-dark btn-sm w-100 py-2" style="letter-spacing: 1px;">SIGN IN</a>
287
<% } %>
288
</div>
289
</div>
290
291
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
292
<div class="info-card border-warning shadow-sm">
293
<div class="small fw-bold text-warning mb-3"><i class="bi bi-gear-wide-connected me-2"></i> ADMINISTRATION</div>
294
<a href="/hinana/admin" class="d-flex justify-content-between align-items-center text-decoration-none" style="color: inherit;">
295
<span class="small"><i class="bi bi-bookmark-star-fill me-1"></i> 책갈피 관리</span>
296
<i class="bi bi-chevron-right text-secondary"></i>
297
</a>
298
</div>
299
<% } %>
300
301
<div class="info-card">
302
<div style="font-size: 0.65rem; color: var(--accent-color); letter-spacing: 3px; font-weight: 700; margin-bottom: 15px;">SYSTEM INFO</div>
303
<ul class="small text-secondary list-unstyled mb-0" style="font-size: 0.75rem;">
304
<li class="mb-1 d-flex justify-content-between">
305
<span>Version</span>
306
<span class="text-end">Ver. 6.5.4.0-Kozeki Ui</span>
307
</li>
308
</ul>
309
</div>
310
311
<div class="mt-auto text-center pt-5">
312
<img src="/image/sign.png" style="width: 160px; opacity: 0.7; mix-blend-mode: multiply;">
313
<div class="mt-4 pt-4 border-top" style="font-size: 0.7rem; color: var(--text-secondary); line-height: 1.8;">
314
<strong>비나래 라운지</strong><br>
315
X - @NoctchillHinana<br>
316
ⓒ 2024~2026. 비나래 | hinana.moe
317
</div>
318
</div>
319
</div>
320
</div>
321
322
<script src="/js/popup.js"></script>
323
<script>if ("serviceWorker" in navigator) { navigator.serviceWorker.register("/sw.js"); }</script>
324
</body>
325
</html>
326