Public Source Viewer
비나래아카이브 개발자 포털
실제 서비스 구조를 살펴볼 수 있는 공개용 코드 뷰어입니다. 인증, 세션, 외부 연동, 토큰, 관리자 식별 등 보안상 민감한 구현은 파일 단위 또는 줄 단위로 검열됩니다.
view/hinana/gallery.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/lounge1.png" />
11
<meta property="og:description" content="비나래 라운지 갤러리"/>
12
<meta property="og:url" content="hinana.moe/hinana/gallery"/>
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; --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
a { text-decoration: none; color: inherit; }
44
45
.global-header {
46
height: 60px; background-color: var(--bg-tertiary); border-bottom: 1px solid var(--border-color);
47
display: flex; align-items: center; justify-content: space-between; padding: 0 40px;
48
position: sticky; top: 0; z-index: 1000; color: white; flex-wrap: wrap;
49
}
50
.header-logo { height: 32px; filter: none !important; -webkit-filter: none !important; mix-blend-mode: normal !important; }
51
.header-brand { display: flex; align-items: center; flex: 0 0 auto; }
52
.header-nav { display: flex; gap: 20px; align-items: center; transition: all 0.3s ease; }
53
54
/* [Layout] */
55
.layout-container {
56
display: flex;
57
min-height: calc(100vh - 60px);
58
background-color: var(--bg-main);
59
width: 100%; max-width: 100vw; overflow-x: hidden;
60
}
61
62
.content-column {
63
flex: 1; padding: 60px 40px;
64
display: flex; flex-direction: column; align-items: center;
65
width: 100%; min-width: 0;
66
}
67
68
/* [Right Sidebar] */
69
.info-column {
70
flex: 0 0 320px;
71
width: 320px;
72
background-color: var(--bg-secondary);
73
border-left: 1px solid var(--border-color);
74
padding: 40px 0;
75
display: flex; flex-direction: column; align-items: center;
76
}
77
78
.info-card {
79
width: 270px;
80
background-color: var(--bg-main);
81
border: 1px solid var(--border-color);
82
border-radius: 12px;
83
padding: 24px 20px;
84
margin-bottom: 20px;
85
box-shadow: var(--shadow-sm);
86
}
87
88
.gallery-hero { text-align: center; margin-bottom: 50px; }
89
.gallery-title { font-size: 2.8rem; font-weight: 700; color: var(--text-primary); margin: 15px 0; letter-spacing: -1px; }
90
91
.gallery-section {
92
width: 100%; background-color: var(--bg-secondary);
93
padding: 40px; border-radius: 4px; border: 1px solid var(--border-color);
94
border-top: 5px solid var(--accent-color) !important; box-shadow: var(--shadow-md);
95
margin-bottom: 40px;
96
}
97
98
.section-label {
99
font-size: 0.65rem; color: var(--accent-color); letter-spacing: 3px;
100
font-weight: 700; text-transform: uppercase; margin-bottom: 10px;
101
}
102
.section-title {
103
font-size: 1.3rem; font-weight: 700; margin-bottom: 30px;
104
padding-bottom: 15px; border-bottom: 1px solid var(--border-color);
105
}
106
107
.color-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 20px; }
108
.color-card {
109
border: 1px solid var(--border-color); border-radius: 8px; overflow: hidden;
110
background-color: var(--bg-main); transition: all 0.2s;
111
}
112
.color-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
113
.color-swatch { height: 80px; width: 100%; }
114
.color-info { padding: 12px 14px; }
115
.color-name { font-weight: 700; font-size: 0.85rem; margin-bottom: 2px; }
116
.color-hex { font-size: 0.75rem; color: var(--text-secondary); font-family: 'Courier New', monospace; }
117
118
.logo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 20px; }
119
.logo-card {
120
border: 1px solid var(--border-color); border-radius: 8px; overflow: hidden;
121
background-color: var(--bg-main); text-align: center; padding: 30px 20px;
122
transition: all 0.2s; cursor: pointer;
123
}
124
.logo-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--accent-color); }
125
.logo-card img { max-height: 48px; max-width: 100%; object-fit: contain; margin-bottom: 15px; }
126
.logo-label { font-weight: 700; font-size: 0.85rem; }
127
128
.gallery-modal .modal-content {
129
background-color: var(--bg-secondary); color: var(--text-primary);
130
border: 1px solid var(--border-color); border-radius: 8px;
131
border-top: 4px solid var(--accent-color);
132
}
133
.gallery-modal .modal-header { border-bottom: 1px solid var(--border-color); }
134
body.dark-mode .gallery-modal .btn-close { filter: invert(1); }
135
.gallery-modal .modal-body { padding: 25px 30px; }
136
.gallery-modal .service-item {
137
display: flex; align-items: center; gap: 15px;
138
padding: 16px; margin-bottom: 12px;
139
background-color: var(--bg-main); border: 1px solid var(--border-color);
140
border-radius: 8px; transition: all 0.2s; text-decoration: none; color: inherit;
141
}
142
.gallery-modal .service-item:hover {
143
border-color: var(--accent-color); transform: translateX(5px); box-shadow: var(--shadow-sm);
144
}
145
.gallery-modal .service-item:last-child { margin-bottom: 0; }
146
.gallery-modal .service-icon {
147
width: 40px; height: 40px; border-radius: 8px;
148
background-color: var(--bg-secondary); display: flex; align-items: center; justify-content: center;
149
font-size: 1.2rem; color: var(--accent-color); flex-shrink: 0;
150
}
151
.gallery-modal .service-name { font-weight: 700; font-size: 0.9rem; margin-bottom: 2px; }
152
.gallery-modal .service-desc { font-size: 0.75rem; color: var(--text-secondary); }
153
154
.footer-area {
155
text-align: center; padding: 40px 20px; margin-top: 20px;
156
font-size: 0.7rem; color: var(--text-secondary); line-height: 1.8;
157
}
158
159
@media (max-width: 1200px) {
160
.global-header { padding: 10px 20px; }
161
.layout-container { flex-direction: column; align-items: center; }
162
.content-column { width: 100%; padding: 40px 20px; }
163
164
.info-column {
165
width: 100%; flex: auto;
166
border-left: none; border-top: 1px solid var(--border-color);
167
padding: 40px 20px;
168
}
169
.info-card { width: 100%; }
170
.info-column > div:last-child { margin-bottom: 60px; }
171
}
172
173
@media (max-width: 991px) {
174
.global-header { height: auto; min-height: 60px; padding: 10px 15px; }
175
.header-brand { order: 1; }
176
.header-nav { gap: 15px !important; order: 2; margin-left: auto; }
177
.header-controls {
178
width: 100%; order: 3; display: flex; justify-content: flex-end;
179
margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.15);
180
}
181
}
182
183
@media (max-width: 768px) {
184
.content-column { padding: 30px 15px; }
185
.gallery-section { padding: 25px 18px; }
186
.gallery-title { font-size: 2rem; }
187
.color-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
188
.logo-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
189
}
190
</style>
191
</head>
192
193
<body class="<%= (typeof theme !== 'undefined' && theme === 'dark') ? 'dark-mode' : '' %>">
194
<header class="global-header">
195
<div class="header-brand">
196
<a href="/hinana/lounge">
197
<img src="/image/lounge1.png" alt="Logo" class="header-logo">
198
</a>
199
</div>
200
<nav class="header-nav">
201
<a href="/hinana/index" class="nav-link text-white-50 small fw-bold">Archive</a>
202
<a href="/hinana/lounge" class="nav-link text-white-50 small fw-bold">Lounge</a>
203
<a href="/hinana/gallery" class="nav-link text-white fw-bold">Gallery</a>
204
</nav>
205
<div class="header-controls" style="display:flex; align-items:center; gap:12px;">
206
<a href="#brand-assets" class="text-white-50 small fw-bold" style="text-decoration:none;">사이트 맵</a>
207
<form action="/toggle-theme" method="POST" style="margin:0;">
208
<button type="submit" class="btn text-white p-1"><i class="bi bi-moon-stars"></i></button>
209
</form>
210
</div>
211
</header>
212
213
<div class="layout-container">
214
<div class="content-column">
215
216
<div class="gallery-hero">
217
<span style="color: var(--accent-color); letter-spacing: 5px; font-weight: bold; font-size: 0.8rem;">LOUNGE GALLERY</span>
218
<h2 class="gallery-title">라운지 갤러리</h2>
219
<div style="width: 60px; height: 1px; background: var(--accent-color); margin: 0 auto;"></div>
220
<p class="text-secondary mt-3">비나래아카이브와 비나래 라운지의 디자인 및 서비스들을 소개합니다.</p>
221
</div>
222
223
<!-- 색상 팔레트 섹션 -->
224
<div class="gallery-section">
225
<div class="section-label">COLOR PALETTE</div>
226
<div class="section-title">비나래아카이브와 비나래 라운지에는 이런 색들이 사용되었어요.</div>
227
228
<div class="color-grid">
229
<div class="color-card">
230
<div class="color-swatch" style="background-color: #FFC639;"></div>
231
<div class="color-info">
232
<div class="color-name">히나나 옐로우</div>
233
<div class="color-hex">#FFC639</div>
234
</div>
235
</div>
236
<div class="color-card">
237
<div class="color-swatch" style="background-color: #1a2238;"></div>
238
<div class="color-info">
239
<div class="color-name">비나래 다크 블루</div>
240
<div class="color-hex">#1a2238</div>
241
</div>
242
</div>
243
<div class="color-card">
244
<div class="color-swatch" style="background-color: #b45309;"></div>
245
<div class="color-info">
246
<div class="color-name">비나래 아카이브 브라운</div>
247
<div class="color-hex">#b45309</div>
248
</div>
249
</div>
250
<div class="color-card">
251
<div class="color-swatch" style="background-color: #c5a059;"></div>
252
<div class="color-info">
253
<div class="color-name">비나래 라운지 골드</div>
254
<div class="color-hex">#c5a059</div>
255
</div>
256
</div>
257
<div class="color-card">
258
<div class="color-swatch" style="background-color: #e4dfd7;"></div>
259
<div class="color-info">
260
<div class="color-name">비나래 아카이브 베이지</div>
261
<div class="color-hex">#e4dfd7</div>
262
</div>
263
</div>
264
<div class="color-card">
265
<div class="color-swatch" style="background-color: #f8f7f5;"></div>
266
<div class="color-info">
267
<div class="color-name">비나래 라운지 아이보리</div>
268
<div class="color-hex">#f8f7f5</div>
269
</div>
270
</div>
271
<div class="color-card">
272
<div class="color-swatch" style="background-color: #0f141e;"></div>
273
<div class="color-info">
274
<div class="color-name">비나래 다크모드 블랙</div>
275
<div class="color-hex">#0f141e</div>
276
</div>
277
</div>
278
<div class="color-card">
279
<div class="color-swatch" style="background-color: #1c1917;"></div>
280
<div class="color-info">
281
<div class="color-name">비나래 아카이브 다크</div>
282
<div class="color-hex">#1c1917</div>
283
</div>
284
</div>
285
<div class="color-card">
286
<div class="color-swatch" style="background-color: #f2f0eb;"></div>
287
<div class="color-info">
288
<div class="color-name">비나래 아카이브 크림</div>
289
<div class="color-hex">#f2f0eb</div>
290
</div>
291
</div>
292
<div class="color-card">
293
<div class="color-swatch" style="background-color: #3e3a36;"></div>
294
<div class="color-info">
295
<div class="color-name">비나래 아카이브 차콜</div>
296
<div class="color-hex">#3e3a36</div>
297
</div>
298
</div>
299
<div class="color-card">
300
<div class="color-swatch" style="background-color: #f59e0b;"></div>
301
<div class="color-info">
302
<div class="color-name">비나래 아카이브 다크모드 앰버</div>
303
<div class="color-hex">#f59e0b</div>
304
</div>
305
</div>
306
<div class="color-card">
307
<div class="color-swatch" style="background-color: #d4b47a;"></div>
308
<div class="color-info">
309
<div class="color-name">비나래 라운지 다크모드 골드</div>
310
<div class="color-hex">#d4b47a</div>
311
</div>
312
</div>
313
<div class="color-card">
314
<div class="color-swatch" style="background-color: #0a0e17;"></div>
315
<div class="color-info">
316
<div class="color-name">특급 히나나호 나이트</div>
317
<div class="color-hex">#0a0e17</div>
318
</div>
319
</div>
320
<div class="color-card">
321
<div class="color-swatch" style="background-color: #1d9bf0;"></div>
322
<div class="color-info">
323
<div class="color-name">비나래 체크마크 블루</div>
324
<div class="color-hex">#1d9bf0</div>
325
</div>
326
</div>
327
<div class="color-card">
328
<div class="color-swatch" style="background-color: #dc2626;"></div>
329
<div class="color-info">
330
<div class="color-name">비나래 레드</div>
331
<div class="color-hex">#dc2626</div>
332
</div>
333
</div>
334
</div>
335
</div>
336
337
<!-- 로고/서비스 섹션 -->
338
<div class="gallery-section" id="brand-assets">
339
<div class="section-label">BRAND ASSETS</div>
340
<div class="section-title">현재 이런 서비스들을 제공하고 있죠.<span style="font-size:0.7em;">(터치 및 클릭시 팝업)</span></div>
341
342
<div class="logo-grid">
343
<div class="logo-card" data-bs-toggle="modal" data-bs-target="#archiveModal">
344
<img src="/image/<%= (typeof theme !== 'undefined' && theme === 'dark') ? 'archive1.png' : 'archive.png' %>" alt="비나래아카이브">
345
<div class="logo-label">비나래아카이브</div>
346
</div>
347
<div class="logo-card" data-bs-toggle="modal" data-bs-target="#libraryModal">
348
<img src="/image/<%= (typeof theme !== 'undefined' && theme === 'dark') ? 'library1.png' : 'library.png' %>" alt="비나래아카이브 도서관">
349
<div class="logo-label">비나래아카이브 도서관</div>
350
</div>
351
<div class="logo-card" data-bs-toggle="modal" data-bs-target="#loungeModal">
352
<img src="/image/<%= (typeof theme !== 'undefined' && theme === 'dark') ? 'lounge1.png' : 'lounge.png' %>" alt="비나래 라운지">
353
<div class="logo-label">비나래 라운지</div>
354
</div>
355
<div class="logo-card" data-bs-toggle="modal" data-bs-target="#railwayModal">
356
<img src="/image/<%= (typeof theme !== 'undefined' && theme === 'dark') ? 'train1.png' : 'train.png' %>" alt="비나래아카이브 철도국">
357
<div class="logo-label">비나래아카이브 철도국</div>
358
</div>
359
</div>
360
</div>
361
362
</div>
363
364
<div class="info-column">
365
<div class="info-card text-center">
366
<div style="font-size: 0.65rem; color: var(--accent-color); letter-spacing: 3px; font-weight: 700; margin-bottom: 20px;">PASSENGER INFO</div>
367
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
368
<div>
369
<% if(username) { %>
370
<a href="/logout?redirect=/hinana/gallery" class="btn btn-outline-dark btn-sm w-100 py-2" style="letter-spacing: 1px;">SIGN OUT</a>
371
<% } else { %>
372
<a href="/login?redirect=/hinana/gallery" class="btn btn-dark btn-sm w-100 py-2" style="letter-spacing: 1px;">SIGN IN</a>
373
<% } %>
374
</div>
375
</div>
376
377
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
378
<div class="info-card border-warning shadow-sm">
379
<div class="small fw-bold text-warning mb-3"><i class="bi bi-gear-wide-connected me-2"></i> ADMINISTRATION</div>
380
<a href="/hinana/admin" class="d-flex justify-content-between align-items-center text-decoration-none" style="color: inherit;">
381
<span class="small"><i class="bi bi-bookmark-star-fill me-1"></i> 책갈피 관리</span>
382
<i class="bi bi-chevron-right text-secondary"></i>
383
</a>
384
</div>
385
<% } %>
386
387
<div class="info-card">
388
<div style="font-size: 0.65rem; color: var(--accent-color); letter-spacing: 3px; font-weight: 700; margin-bottom: 15px;">SYSTEM INFO</div>
389
<ul class="small text-secondary list-unstyled mb-0" style="font-size: 0.75rem;">
390
<li class="mb-1 d-flex justify-content-between">
391
<span>Version</span>
392
<span class="text-end">Ver. 6.5.4.0-Kozeki Ui</span>
393
</li>
394
</ul>
395
</div>
396
397
<div class="mt-auto text-center pt-5">
398
<img src="/image/sign.png" style="width: 160px; opacity: 0.7; mix-blend-mode: multiply;">
399
<div class="mt-4 pt-4 border-top" style="font-size: 0.7rem; color: var(--text-secondary); line-height: 1.8;">
400
<strong>비나래 라운지</strong><br>
401
X - @NoctchillHinana<br>
402
ⓒ 2024~2026. 비나래 | hinana.moe
403
</div>
404
</div>
405
</div>
406
</div>
407
408
<!-- 비나래아카이브 모달 -->
409
<div class="modal fade gallery-modal" id="archiveModal" tabindex="-1">
410
<div class="modal-dialog modal-dialog-centered">
411
<div class="modal-content">
412
<div class="modal-header">
413
<h6 class="modal-title fw-bold">비나래아카이브</h6>
414
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
415
</div>
416
<div class="modal-body">
417
<a href="/" class="service-item">
418
<div class="service-icon"><i class="bi bi-house-door"></i></div>
419
<div>
420
<div class="service-name">메인 화면</div>
421
<div class="service-desc">hinana.moe의 첫 번째 페이지. 비나래아카이브의 시작점이에요.</div>
422
</div>
423
</a>
424
<a href="/hinana/index" class="service-item">
425
<div class="service-icon"><i class="bi bi-archive"></i></div>
426
<div>
427
<div class="service-name">비나래아카이브</div>
428
<div class="service-desc">비나래씨의 SNS이자 모두의 SNS. 일상과 생각을 기록하는 아카이브 공간이에요.</div>
429
</div>
430
</a>
431
<a href="/hinana/info" class="service-item">
432
<div class="service-icon"><i class="bi bi-person-circle"></i></div>
433
<div>
434
<div class="service-name">비나래씨란?</div>
435
<div class="service-desc">비나래씨에 대해 알아볼 수 있는 소개 페이지예요.</div>
436
</div>
437
</a>
438
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
439
<a href="/hinana/personal-notes" class="service-item">
440
<div class="service-icon"><i class="bi bi-journal"></i></div>
441
<div>
442
<div class="service-name">개인 노트</div>
443
<div class="service-desc">비나래씨만 사용하는 개인 노트 공간이에요.</div>
444
</div>
445
</a>
446
<% } %>
447
</div>
448
</div>
449
</div>
450
</div>
451
452
<!-- 비나래아카이브 도서관 모달 -->
453
<div class="modal fade gallery-modal" id="libraryModal" tabindex="-1">
454
<div class="modal-dialog modal-dialog-centered">
455
<div class="modal-content">
456
<div class="modal-header">
457
<h6 class="modal-title fw-bold">비나래아카이브 도서관</h6>
458
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
459
</div>
460
<div class="modal-body">
461
<a href="/hinana/blog" class="service-item">
462
<div class="service-icon"><i class="bi bi-book"></i></div>
463
<div>
464
<div class="service-name">비나래아카이브 도서관</div>
465
<div class="service-desc">비나래씨의 블로그. 긴 글과 이야기를 담아두는 도서관이에요.</div>
466
</div>
467
</a>
468
</div>
469
</div>
470
</div>
471
</div>
472
473
<!-- 비나래 라운지 모달 -->
474
<div class="modal fade gallery-modal" id="loungeModal" tabindex="-1">
475
<div class="modal-dialog modal-dialog-centered">
476
<div class="modal-content">
477
<div class="modal-header">
478
<h6 class="modal-title fw-bold">비나래 라운지</h6>
479
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
480
</div>
481
<div class="modal-body">
482
<a href="/hinana/lounge" class="service-item">
483
<div class="service-icon"><i class="bi bi-cup-hot"></i></div>
484
<div>
485
<div class="service-name">비나래 라운지</div>
486
<div class="service-desc">아카이브를 나와 라운지로. 다양한 기능들의 허브예요.</div>
487
</div>
488
</a>
489
<a href="/hinana/plaza" class="service-item">
490
<div class="service-icon"><i class="bi bi-chat-dots"></i></div>
491
<div>
492
<div class="service-name">비나래 광장</div>
493
<div class="service-desc">24시간 동안 유지되는 실시간 광장. 자유롭게 이야기해요.</div>
494
</div>
495
</a>
496
<a href="/hinana/gallery" class="service-item">
497
<div class="service-icon"><i class="bi bi-palette"></i></div>
498
<div>
499
<div class="service-name">라운지 갤러리</div>
500
<div class="service-desc">비나래씨의 디자인과 서비스들을 전시하는 갤러리예요.</div>
501
</div>
502
</a>
503
<a href="/hinana/tetris" class="service-item">
504
<div class="service-icon"><i class="bi bi-controller"></i></div>
505
<div>
506
<div class="service-name">TETRIS</div>
507
<div class="service-desc">라운지에서 즐기는 테트리스 게임이에요.</div>
508
</div>
509
</a>
510
<a href="/hinana/shop" class="service-item">
511
<div class="service-icon"><i class="bi bi-bookmark-star"></i></div>
512
<div>
513
<div class="service-name">책갈피 교환소</div>
514
<div class="service-desc">책갈피로 다양한 커스텀 아이템을 구매할 수 있어요.</div>
515
</div>
516
</a>
517
<a href="/hinana/image" class="service-item">
518
<div class="service-icon"><i class="bi bi-image"></i></div>
519
<div>
520
<div class="service-name">이미지 편집기</div>
521
<div class="service-desc">이미지를 불러와 원하는 위치에 텍스트를 추가하고 저장할 수 있어요.</div>
522
</div>
523
</a>
524
<a href="/hinana/exhibition" class="service-item">
525
<div class="service-icon"><i class="bi bi-easel2"></i></div>
526
<div>
527
<div class="service-name">특별전 <span style="font-size:0.7em; opacity:0.6;">Claude Design 테스트</span></div>
528
<div class="service-desc">Claude Design으로 제작한 미술관 스타일의 갤러리 특별전시입니다.</div>
529
</div>
530
</a>
531
<a href="/hinana/echo" class="service-item">
532
<div class="service-icon"><i class="bi bi-soundwave"></i></div>
533
<div>
534
<div class="service-name">에코 스튜디오</div>
535
<div class="service-desc">음악 파일에 노래방 스타일 에코 효과를 입혀 저장할 수 있어요.</div>
536
</div>
537
</a>
538
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
539
<div class="service-icon"><i class="bi bi-calculator"></i></div>
540
<div>
541
<div class="service-name">AI 토큰 계산기</div>
542
<div class="service-desc">GPT-5.5 기준으로 텍스트의 토큰 수와 예상 비용을 계산합니다.</div>
543
</div>
544
</a>
545
<a href="/hinana/subway" class="service-item">
546
<div class="service-icon"><i class="bi bi-train-front"></i></div>
547
<div>
548
<div class="service-name">열차 위치 조회</div>
549
<div class="service-desc">서울시 지하철 API로 열번의 현재 위치와 진입·도착·출발 상태를 확인합니다.</div>
550
</div>
551
</a>
552
</div>
553
</div>
554
</div>
555
</div>
556
557
<!-- 비나래아카이브 철도국 모달 -->
558
<div class="modal fade gallery-modal" id="railwayModal" tabindex="-1">
559
<div class="modal-dialog modal-dialog-centered">
560
<div class="modal-content">
561
<div class="modal-header">
562
<h6 class="modal-title fw-bold">비나래아카이브 철도국</h6>
563
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
564
</div>
565
<div class="modal-body">
566
<a href="/hinana/train" class="service-item">
567
<div class="service-icon"><i class="bi bi-train-front"></i></div>
568
<div>
569
<div class="service-name">특급 히나나호</div>
570
<div class="service-desc">비내리는 열차를 탑승하여 기차 소리를 들으며 여행해보세요.</div>
571
</div>
572
</a>
573
<a href="/hinana/kivotosExp" class="service-item">
574
<div class="service-icon"><i class="bi bi-train-lightrail-front"></i></div>
575
<div>
576
<div class="service-name">키보토스 광역급행철도</div>
577
<div class="service-desc">플랫폼에서 승객을 만나고 노조미 또는 히카리 특급을 탑승해보세요.</div>
578
</div>
579
</a>
580
<a href="/hinana/lcd" class="service-item">
581
<div class="service-icon"><i class="bi bi-display"></i></div>
582
<div>
583
<div class="service-name">키보토스광역급행철도 LCD</div>
584
<div class="service-desc">키보토스 광역급행철도 열차 내 LCD 안내판을 재현합니다.</div>
585
</div>
586
</a>
587
</div>
588
</div>
589
</div>
590
</div>
591
592
<script>if ("serviceWorker" in navigator) { navigator.serviceWorker.register("/sw.js"); }</script>
593
</body>
594
</html>
595