dqtweb commited on
Commit
7f09b2f
·
verified ·
1 Parent(s): 922e1bd

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +857 -19
index.html CHANGED
@@ -1,19 +1,857 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Capybara - Three.js Interactive Showcase</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,300&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;1,9..144,400&family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
11
+
12
+ <script>
13
+ tailwind.config = {
14
+ theme: {
15
+ extend: {
16
+ fontFamily: {
17
+ display: ['"Fraunces"', 'serif'],
18
+ body: ['"DM Sans"', 'sans-serif'],
19
+ alt: ['"Outfit"', 'sans-serif'],
20
+ },
21
+ colors: {
22
+ 'capy-1': '#B88050',
23
+ 'capy-2': '#9D6B3F',
24
+ 'capy-3': '#7A5330',
25
+ 'capy-dark': '#4A3525',
26
+ 'capy-light': '#C99A6B',
27
+ 'capy-rose': '#D4A594',
28
+ 'capy-sand': '#F2E6D8',
29
+ 'capy-sky': '#8BBCC7',
30
+ 'capy-teal': '#5A9BA8',
31
+ 'capy-ocean': '#3D7A88',
32
+ 'capy-grass': '#7BA872',
33
+ 'capy-leaf': '#5E8A56',
34
+ }
35
+ }
36
+ }
37
+ }
38
+ </script>
39
+
40
+ <style>
41
+ :root {
42
+ --bg-color: #F2E6D8;
43
+ --accent: #B88050;
44
+ --text: #3D2B1F;
45
+ --card-bg: rgba(255, 255, 255, 0.55);
46
+ }
47
+
48
+ * { margin: 0; padding: 0; box-sizing: border-box; }
49
+
50
+ html, body {
51
+ width: 100%;
52
+ height: 100%;
53
+ overflow: hidden;
54
+ font-family: 'DM Sans', sans-serif;
55
+ background: var(--bg-color);
56
+ }
57
+
58
+ #three-canvas {
59
+ position: fixed;
60
+ top: 0; left: 0;
61
+ width: 100%; height: 100%;
62
+ z-index: 0;
63
+ }
64
+
65
+ .ui-layer {
66
+ position: fixed;
67
+ top: 0; left: 0;
68
+ width: 100%; height: 100%;
69
+ z-index: 10;
70
+ pointer-events: none;
71
+ }
72
+
73
+ .ui-layer > * { pointer-events: auto; }
74
+
75
+ /* Glass card */
76
+ .glass {
77
+ background: var(--card-bg);
78
+ backdrop-filter: blur(16px) saturate(1.4);
79
+ -webkit-backdrop-filter: blur(16px) saturate(1.4);
80
+ border: 1px solid rgba(255,255,255,0.4);
81
+ box-shadow:
82
+ 0 1px 2px rgba(61, 43, 31, 0.04),
83
+ 0 4px 12px rgba(61, 43, 31, 0.06),
84
+ 0 12px 32px rgba(61, 43, 31, 0.08),
85
+ inset 0 1px 0 rgba(255,255,255,0.6);
86
+ border-radius: 20px;
87
+ }
88
+
89
+ /* Pills */
90
+ .pill {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ gap: 6px;
94
+ padding: 6px 14px;
95
+ border-radius: 999px;
96
+ font-size: 12px;
97
+ font-weight: 500;
98
+ letter-spacing: 0.3px;
99
+ cursor: pointer;
100
+ user-select: none;
101
+ transition: all 0.35s cubic-bezier(0.22, 1, 0.36, 1);
102
+ border: 1px solid rgba(255,255,255,0.5);
103
+ backdrop-filter: blur(8px);
104
+ -webkit-backdrop-filter: blur(8px);
105
+ font-family: 'Outfit', sans-serif;
106
+ }
107
+
108
+ .pill:hover {
109
+ transform: translateY(-2px) scale(1.03);
110
+ box-shadow: 0 6px 20px rgba(61,43,31,0.12);
111
+ }
112
+
113
+ .pill:active { transform: translateY(0) scale(0.97); }
114
+
115
+ .pill.active {
116
+ box-shadow: 0 0 0 2px var(--accent), 0 4px 16px rgba(184,128,80,0.2);
117
+ }
118
+
119
+ /* Buttons */
120
+ .btn-primary {
121
+ display: inline-flex;
122
+ align-items: center;
123
+ gap: 8px;
124
+ padding: 10px 22px;
125
+ border-radius: 14px;
126
+ font-family: 'Outfit', sans-serif;
127
+ font-weight: 500;
128
+ font-size: 13px;
129
+ letter-spacing: 0.2px;
130
+ color: #fff;
131
+ background: var(--accent);
132
+ border: none;
133
+ cursor: pointer;
134
+ transition: all 0.3s cubic-bezier(0.22, 1, 0.36, 1);
135
+ box-shadow: 0 2px 8px rgba(184,128,80,0.25), 0 4px 20px rgba(184,128,80,0.15);
136
+ }
137
+
138
+ .btn-primary:hover {
139
+ transform: translateY(-2px);
140
+ box-shadow: 0 4px 14px rgba(184,128,80,0.35), 0 8px 28px rgba(184,128,80,0.2);
141
+ }
142
+
143
+ .btn-primary:active { transform: translateY(0); }
144
+
145
+ .btn-secondary {
146
+ display: inline-flex;
147
+ align-items: center;
148
+ gap: 6px;
149
+ padding: 8px 16px;
150
+ border-radius: 12px;
151
+ font-family: 'Outfit', sans-serif;
152
+ font-weight: 500;
153
+ font-size: 12px;
154
+ letter-spacing: 0.2px;
155
+ color: var(--text);
156
+ background: rgba(255,255,255,0.55);
157
+ border: 1px solid rgba(255,255,255,0.5);
158
+ cursor: pointer;
159
+ transition: all 0.3s ease;
160
+ backdrop-filter: blur(8px);
161
+ -webkit-backdrop-filter: blur(8px);
162
+ }
163
+
164
+ .btn-secondary:hover {
165
+ background: rgba(255,255,255,0.8);
166
+ transform: translateY(-1px);
167
+ }
168
+
169
+ /* Loading screen */
170
+ #loading-screen {
171
+ position: fixed;
172
+ top: 0; left: 0;
173
+ width: 100%; height: 100%;
174
+ z-index: 200;
175
+ background: #F2E6D8;
176
+ display: flex;
177
+ flex-direction: column;
178
+ align-items: center;
179
+ justify-content: center;
180
+ transition: opacity 0.8s ease, visibility 0.8s ease;
181
+ }
182
+
183
+ #loading-screen.hidden { opacity: 0; visibility: hidden; }
184
+
185
+ .loader-dots {
186
+ display: flex;
187
+ gap: 8px;
188
+ margin-top: 24px;
189
+ }
190
+
191
+ .loader-dots span {
192
+ width: 10px; height: 10px;
193
+ border-radius: 50%;
194
+ background: var(--accent);
195
+ animation: bounce 1.4s infinite ease-in-out both;
196
+ }
197
+
198
+ .loader-dots span:nth-child(1) { animation-delay: -0.32s; }
199
+ .loader-dots span:nth-child(2) { animation-delay: -0.16s; }
200
+
201
+ @keyframes bounce {
202
+ 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
203
+ 40% { transform: scale(1); opacity: 1; }
204
+ }
205
+
206
+ /* Tooltip */
207
+ .tooltip {
208
+ position: relative;
209
+ }
210
+
211
+ .tooltip::after {
212
+ content: attr(data-tip);
213
+ position: absolute;
214
+ bottom: calc(100% + 8px);
215
+ left: 50%;
216
+ transform: translateX(-50%) translateY(4px);
217
+ padding: 5px 12px;
218
+ background: rgba(61, 43, 31, 0.9);
219
+ color: #fff;
220
+ font-size: 11px;
221
+ border-radius: 8px;
222
+ white-space: nowrap;
223
+ opacity: 0;
224
+ pointer-events: none;
225
+ transition: all 0.25s ease;
226
+ font-family: 'Outfit', sans-serif;
227
+ font-weight: 400;
228
+ }
229
+
230
+ .tooltip:hover::after {
231
+ opacity: 1;
232
+ transform: translateX(-50%) translateY(0);
233
+ }
234
+
235
+ /* Scrollbar */
236
+ .custom-scroll::-webkit-scrollbar { width: 4px; }
237
+ .custom-scroll::-webkit-scrollbar-track { background: transparent; }
238
+ .custom-scroll::-webkit-scrollbar-thumb {
239
+ background: rgba(184,128,80,0.25);
240
+ border-radius: 4px;
241
+ }
242
+
243
+ /* Floating label animation */
244
+ @keyframes floatLabel {
245
+ 0%, 100% { transform: translateY(0); }
246
+ 50% { transform: translateY(-4px); }
247
+ }
248
+
249
+ .float-anim { animation: floatLabel 3s ease-in-out infinite; }
250
+
251
+ /* Fade in animation */
252
+ @keyframes slideUp {
253
+ from { opacity: 0; transform: translateY(20px); }
254
+ to { opacity: 1; transform: translateY(0); }
255
+ }
256
+
257
+ .anim-in { animation: slideUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards; }
258
+ .anim-delay-1 { animation-delay: 0.1s; opacity: 0; }
259
+ .anim-delay-2 { animation-delay: 0.25s; opacity: 0; }
260
+ .anim-delay-3 { animation-delay: 0.4s; opacity: 0; }
261
+ .anim-delay-4 { animation-delay: 0.55s; opacity: 0; }
262
+
263
+ /* Floating info card */
264
+ .info-card {
265
+ position: absolute;
266
+ pointer-events: none;
267
+ opacity: 0;
268
+ transition: opacity 0.3s ease;
269
+ z-index: 20;
270
+ }
271
+
272
+ .info-card.visible { opacity: 1; }
273
+
274
+ /* Separator line */
275
+ .sep {
276
+ width: 32px;
277
+ height: 3px;
278
+ border-radius: 2px;
279
+ background: var(--accent);
280
+ margin: 8px 0;
281
+ }
282
+
283
+ /* Tag dot */
284
+ .tag-dot {
285
+ width: 6px; height: 6px;
286
+ border-radius: 50%;
287
+ }
288
+
289
+ /* Part info card that follows mouse */
290
+ .part-info {
291
+ position: fixed;
292
+ pointer-events: none;
293
+ z-index: 100;
294
+ opacity: 0;
295
+ transition: opacity 0.2s ease;
296
+ transform: translate(-50%, -100%);
297
+ margin-top: -12px;
298
+ }
299
+
300
+ .part-info.visible { opacity: 1; }
301
+
302
+ /* Custom 3D cursor hint */
303
+ .cursor-hint {
304
+ position: fixed;
305
+ bottom: 32px;
306
+ left: 50%;
307
+ transform: translateX(-50%);
308
+ z-index: 20;
309
+ display: flex;
310
+ align-items: center;
311
+ gap: 8px;
312
+ padding: 8px 18px;
313
+ border-radius: 999px;
314
+ background: rgba(255,255,255,0.5);
315
+ backdrop-filter: blur(12px);
316
+ border: 1px solid rgba(255,255,255,0.4);
317
+ font-family: 'Outfit', sans-serif;
318
+ font-size: 11px;
319
+ color: var(--text);
320
+ opacity: 0.7;
321
+ pointer-events: none;
322
+ transition: opacity 0.5s ease;
323
+ }
324
+
325
+ .cursor-hint.fade { opacity: 0; }
326
+
327
+ /* Decorative blob */
328
+ .blob {
329
+ position: fixed;
330
+ border-radius: 50%;
331
+ filter: blur(80px);
332
+ opacity: 0.15;
333
+ pointer-events: none;
334
+ z-index: 1;
335
+ }
336
+
337
+ /* Photo dot */
338
+ .photo-dot {
339
+ position: absolute;
340
+ width: 12px; height: 12px;
341
+ border-radius: 50%;
342
+ background: rgba(255,255,255,0.7);
343
+ border: 2px solid var(--accent);
344
+ cursor: pointer;
345
+ z-index: 20;
346
+ transition: all 0.3s ease;
347
+ }
348
+
349
+ .photo-dot:hover {
350
+ transform: scale(1.4);
351
+ background: var(--accent);
352
+ }
353
+
354
+ .photo-dot.active {
355
+ background: var(--accent);
356
+ box-shadow: 0 0 0 4px rgba(184,128,80,0.2);
357
+ }
358
+
359
+ .photo-line {
360
+ position: absolute;
361
+ height: 1px;
362
+ background: linear-gradient(90deg, var(--accent), transparent);
363
+ transform-origin: left center;
364
+ pointer-events: none;
365
+ opacity: 0;
366
+ transition: opacity 0.3s ease;
367
+ }
368
+
369
+ .photo-dot:hover + .photo-line,
370
+ .photo-dot.active + .photo-line { opacity: 0.5; }
371
+
372
+ /* Keyframe for gentle pulse */
373
+ @keyframes gentlePulse {
374
+ 0%, 100% { transform: scale(1); }
375
+ 50% { transform: scale(1.15); }
376
+ }
377
+
378
+ .pulse { animation: gentlePulse 2s ease-in-out infinite; }
379
+ </style>
380
+
381
+ <script type="importmap">
382
+ {
383
+ "imports": {
384
+ "three": "https://unpkg.com/three@0.160.0/build/three.module.js",
385
+ "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
386
+ }
387
+ }
388
+ </script>
389
+ </head>
390
+
391
+ <body>
392
+
393
+ <!-- Decorative ambient blobs -->
394
+ <div class="blob" style="width:400px;height:400px;background:#B88050;top:-100px;left:-100px;"></div>
395
+ <div class="blob" style="width:300px;height:300px;background:#5A9BA8;bottom:-50px;right:-50px;"></div>
396
+ <div class="blob" style="width:250px;height:250px;background:#7BA872;top:40%;right:10%;"></div>
397
+
398
+ <!-- Loading Screen -->
399
+ <div id="loading-screen">
400
+ <div class="text-center">
401
+ <div class="w-20 h-20 rounded-2xl bg-capy-1 flex items-center justify-center mx-auto mb-6" style="box-shadow: 0 8px 32px rgba(184,128,80,0.25);">
402
+ <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
403
+ <circle cx="9" cy="9" r="1.5"/>
404
+ <circle cx="15" cy="9" r="1.5"/>
405
+ <path d="M7 13.5C7 13.5 9 15.5 12 15.5C15 15.5 17 13.5 17 13.5"/>
406
+ </svg>
407
+ </div>
408
+ <h1 class="font-display text-2xl text-capy-dark mb-1" style="font-weight:500;">Capybara</h1>
409
+ <p class="font-body text-sm text-capy-dark/50">Loading 3D scene...</p>
410
+ </div>
411
+ <div class="loader-dots">
412
+ <span></span><span></span><span></span>
413
+ </div>
414
+ </div>
415
+
416
+ <!-- Three.js Canvas -->
417
+ <canvas id="three-canvas"></canvas>
418
+
419
+ <!-- UI Layer -->
420
+ <div class="ui-layer">
421
+
422
+ <!-- Top Header -->
423
+ <div class="w-full px-5 py-4 flex items-center justify-between">
424
+ <!-- Logo -->
425
+ <div class="flex items-center gap-3 anim-in anim-delay-1">
426
+ <div class="w-9 h-9 rounded-xl bg-capy-1 flex items-center justify-center" style="box-shadow: 0 2px 10px rgba(184,128,80,0.3);">
427
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
428
+ <circle cx="9" cy="9" r="1.5"/>
429
+ <circle cx="15" cy="9" r="1.5"/>
430
+ <path d="M7 13.5C7 13.5 9 15.5 12 15.5C15 15.5 17 13.5 17 13.5"/>
431
+ </svg>
432
+ </div>
433
+ <div>
434
+ <h1 class="font-display text-base text-capy-dark leading-tight" style="font-weight:600;">Capybara</h1>
435
+ <p class="font-body text-[10px] text-capy-dark/40 -mt-0.5">Low Poly 3D Showcase</p>
436
+ </div>
437
+ </div>
438
+
439
+ <!-- Top Right Links -->
440
+ <div class="flex items-center gap-2 anim-in anim-delay-1">
441
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="pill" style="background:rgba(184,128,80,0.1);color:var(--accent);">
442
+ <span style="font-size:13px;">&#9829;</span> Built with anycoder
443
+ </a>
444
+ <a href="#" class="pill" style="background:rgba(255,255,255,0.6);color:var(--text);">
445
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
446
+ <circle cx="12" cy="12" r="10"/>
447
+ <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/>
448
+ <line x1="12" y1="17" x2="12.01" y2="17"/>
449
+ </svg>
450
+ Help
451
+ </a>
452
+ </div>
453
+ </div>
454
+
455
+ <!-- Left Info Panel -->
456
+ <div class="absolute left-5 top-1/2 -translate-y-1/2 anim-in anim-delay-2" style="max-width:270px;">
457
+ <div class="glass p-6" style="border-radius:24px;">
458
+ <!-- Tag -->
459
+ <div class="flex items-center gap-2 mb-3">
460
+ <span class="tag-dot" style="background:#7BA872;"></span>
461
+ <span class="font-alt text-[11px] font-semibold uppercase tracking-widest text-capy-leaf">Interactive</span>
462
+ </div>
463
+
464
+ <h2 class="font-display text-2xl text-capy-dark leading-tight mb-1" style="font-weight:600;">
465
+ The World's<br>Most Chill Animal
466
+ </h2>
467
+ <div class="sep"></div>
468
+
469
+ <p class="font-body text-[13px] text-capy-dark/65 leading-relaxed mb-4">
470
+ Capybaras are the largest living rodents, native to South America. Known for their incredibly chill and social nature.
471
+ </p>
472
+
473
+ <!-- Stats -->
474
+ <div class="grid grid-cols-3 gap-2 mb-5">
475
+ <div class="text-center p-2 rounded-xl" style="background:rgba(184,128,80,0.08);">
476
+ <div class="font-alt text-lg font-bold text-capy-1 leading-none">1.3m</div>
477
+ <div class="font-body text-[9px] text-capy-dark/40 mt-1 uppercase tracking-wider">Length</div>
478
+ </div>
479
+ <div class="text-center p-2 rounded-xl" style="background:rgba(90,155,168,0.08);">
480
+ <div class="font-alt text-lg font-bold text-capy-teal leading-none">66kg</div>
481
+ <div class="font-body text-[9px] text-capy-dark/40 mt-1 uppercase tracking-wider">Weight</div>
482
+ </div>
483
+ <div class="text-center p-2 rounded-xl" style="background:rgba(123,168,114,0.08);">
484
+ <div class="font-alt text-lg font-bold text-capy-grass leading-none">10yr</div>
485
+ <div class="font-body text-[9px] text-capy-dark/40 mt-1 uppercase tracking-wider">Lifespan</div>
486
+ </div>
487
+ </div>
488
+
489
+ <!-- Description -->
490
+ <p class="font-body text-[12px] text-capy-dark/50 leading-relaxed mb-5">
491
+ These gentle giants spend most of their day in water, grazing on grasses, and hanging out with birds, monkeys, and even crocodiles.
492
+ </p>
493
+
494
+ <!-- Body parts -->
495
+ <div class="mb-4">
496
+ <p class="font-alt text-[10px] font-semibold uppercase tracking-widest text-capy-dark/30 mb-2">Anatomy</p>
497
+ <div class="flex flex-wrap gap-1.5">
498
+ <span class="pill tooltip" data-tip="Click to inspect" style="background:rgba(184,128,80,0.1);color:var(--accent);" onclick="app.highlightPart('head')">Head</span>
499
+ <span class="pill tooltip" data-tip="Click to inspect" style="background:rgba(184,128,80,0.1);color:var(--accent);" onclick="app.highlightPart('ears')">Ears</span>
500
+ <span class="pill tooltip" data-tip="Click to inspect" style="background:rgba(184,128,80,0.1);color:var(--accent);" onclick="app.highlightPart('body')">Body</span>
501
+ <span class="pill tooltip" data-tip="Click to inspect" style="background:rgba(184,128,80,0.1);color:var(--accent);" onclick="app.highlightPart('legs')">Legs</span>
502
+ <span class="pill tooltip" data-tip="Click to inspect" style="background:rgba(184,128,80,0.1);color:var(--accent);" onclick="app.highlightPart('tail')">Tail</span>
503
+ </div>
504
+ </div>
505
+
506
+ <!-- Colors -->
507
+ <div class="mb-4">
508
+ <p class="font-alt text-[10px] font-semibold uppercase tracking-widest text-capy-dark/30 mb-2">Coat Color</p>
509
+ <div class="flex items-center gap-2">
510
+ <button class="w-7 h-7 rounded-full border-2 border-transparent hover:border-capy-1 transition-all tooltip" data-tip="Classic Brown" style="background:#B88050;" onclick="app.setCoatColor('#B88050')"></button>
511
+ <button class="w-7 h-7 rounded-full border-2 border-transparent hover:border-capy-1 transition-all tooltip" data-tip="Dark Chocolate" style="background:#7A5330;" onclick="app.setCoatColor('#7A5330')"></button>
512
+ <button class="w-7 h-7 rounded-full border-2 border-transparent hover:border-capy-1 transition-all tooltip" data-tip="Golden Tan" style="background:#D4A068;" onclick="app.setCoatColor('#D4A068')"></button>
513
+ <button class="w-7 h-7 rounded-full border-2 border-transparent hover:border-capy-1 transition-all tooltip" data-tip="Warm Russet" style="background:#C47A45;" onclick="app.setCoatColor('#C47A45')"></button>
514
+ <button class="w-7 h-7 rounded-full border-2 border-transparent hover:border-capy-1 transition-all tooltip" data-tip="Cool Sand" style="background:#D2B898;" onclick="app.setCoatColor('#D2B898')"></button>
515
+ </div>
516
+ </div>
517
+
518
+ <!-- Fact -->
519
+ <div class="rounded-xl p-3" style="background:rgba(123,168,114,0.08);">
520
+ <div class="flex items-start gap-2">
521
+ <span class="text-base mt-[-2px]">&#9734;</span>
522
+ <div>
523
+ <p class="font-body text-[12px] text-capy-dark/70 leading-snug">
524
+ Capybaras can stay underwater for up to <span class="font-semibold text-capy-grass">5 minutes</span> to hide from predators!
525
+ </p>
526
+ </div>
527
+ </div>
528
+ </div>
529
+ </div>
530
+ </div>
531
+
532
+ <!-- Bottom Controls -->
533
+ <div class="absolute bottom-6 left-1/2 -translate-x-1/2 anim-in anim-delay-3">
534
+ <div class="glass px-4 py-3 flex items-center gap-3" style="border-radius:20px;">
535
+ <button class="btn-secondary tooltip" data-tip="Rotate around" onclick="app.toggleRotation()">
536
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
537
+ <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
538
+ <polyline points="21 3 21 9 15 9"/>
539
+ </svg>
540
+ <span id="rot-label">Rotate</span>
541
+ </button>
542
+
543
+ <div class="w-px h-5" style="background:rgba(61,43,31,0.12);"></div>
544
+
545
+ <button class="btn-secondary tooltip" data-tip="Jump animation" onclick="app.triggerJump()">
546
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
547
+ <polyline points="23 18 13.5 8.5 8.5 13.5 1 6"/>
548
+ <polyline points="17 18 23 18 23 12"/>
549
+ </svg>
550
+ Jump
551
+ </button>
552
+
553
+ <button class="btn-secondary tooltip" data-tip="Toggle movement" onclick="app.toggleAnim()">
554
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
555
+ <polygon points="5 3 19 12 5 21 5 3"/>
556
+ </svg>
557
+ <span id="anim-label">Pause</span>
558
+ </button>
559
+
560
+ <div class="w-px h-5" style="background:rgba(61,43,31,0.12);"></div>
561
+
562
+ <button class="btn-secondary tooltip" data-tip="Reset view" onclick="app.resetView()">
563
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
564
+ <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
565
+ <polyline points="9 22 9 12 15 12 15 22"/>
566
+ </svg>
567
+ Reset
568
+ </button>
569
+ </div>
570
+ </div>
571
+
572
+ <!-- Right Panel -->
573
+ <div class="absolute right-5 top-1/2 -translate-y-1/2 anim-in anim-delay-4" style="max-width:220px;">
574
+ <div class="glass p-5" style="border-radius:20px;">
575
+
576
+ <!-- Status -->
577
+ <div class="mb-4">
578
+ <p class="font-alt text-[10px] font-semibold uppercase tracking-widest text-capy-dark/30 mb-2">Current Mood</p>
579
+ <div class="flex items-center gap-3">
580
+ <div class="w-10 h-10 rounded-xl flex items-center justify-center" style="background:rgba(184,128,80,0.1);">
581
+ <span class="text-xl float-anim">&#9786;</span>
582
+ </div>
583
+ <div>
584
+ <p class="font-alt text-sm font-semibold text-capy-dark">Relaxed</p>
585
+ <p class="font-body text-[10px] text-capy-dark/40">Enjoying the warmth</p>
586
+ </div>
587
+ </div>
588
+ </div>
589
+
590
+ <!-- Stats bar -->
591
+ <div class="mb-4 space-y-2.5">
592
+ <div>
593
+ <div class="flex justify-between mb-1">
594
+ <span class="font-body text-[10px] text-capy-dark/50">Chill Level</span>
595
+ <span class="font-body text-[10px] font-semibold text-capy-1">100%</span>
596
+ </div>
597
+ <div class="h-1.5 rounded-full" style="background:rgba(184,128,80,0.12);">
598
+ <div class="h-full rounded-full transition-all duration-700" style="width:100%;background:var(--accent);"></div>
599
+ </div>
600
+ </div>
601
+ <div>
602
+ <div class="flex justify-between mb-1">
603
+ <span class="font-body text-[10px] text-capy-dark/50">Socialness</span>
604
+ <span class="font-body text-[10px] font-semibold text-capy-teal">98%</span>
605
+ </div>
606
+ <div class="h-1.5 rounded-full" style="background:rgba(90,155,168,0.12);">
607
+ <div class="h-full rounded-full transition-all duration-700" style="width:98%;background:#5A9BA8;"></div>
608
+ </div>
609
+ </div>
610
+ <div>
611
+ <div class="flex justify-between mb-1">
612
+ <span class="font-body text-[10px] text-capy-dark/50">Hunger</span>
613
+ <span class="font-body text-[10px] font-semibold text-capy-grass">72%</span>
614
+ </div>
615
+ <div class="h-1.5 rounded-full" style="background:rgba(123,168,114,0.12);">
616
+ <div class="h-full rounded-full transition-all duration-700" style="width:72%;background:#7BA872;"></div>
617
+ </div>
618
+ </div>
619
+ </div>
620
+
621
+ <!-- Mini gallery -->
622
+ <div class="mb-4">
623
+ <p class="font-alt text-[10px] font-semibold uppercase tracking-widest text-capy-dark/30 mb-2">Fun Facts</p>
624
+ <div class="space-y-2">
625
+ <div class="flex items-start gap-2 p-2 rounded-lg" style="background:rgba(90,155,168,0.06);">
626
+ <span class="text-xs mt-0.5">&#127807;</span>
627
+ <p class="font-body text-[11px] text-capy-dark/60 leading-snug">Capybaras have webbed feet, making them excellent swimmers.</p>
628
+ </div>
629
+ <div class="flex items-start gap-2 p-2 rounded-lg" style="background:rgba(123,168,114,0.06);">
630
+ <span class="text-xs mt-0.5">&#127912;</span>
631
+ <p class="font-body text-[11px] text-capy-dark/60 leading-snug">Their scientific name is <em>Hydrochoerus hydrochaeris</em>.</p>
632
+ </div>
633
+ </div>
634
+ </div>
635
+
636
+ <!-- Habitat tag -->
637
+ <div class="flex items-center gap-2 p-3 rounded-xl" style="background:rgba(90,155,168,0.08);">
638
+ <span class="text-lg">&#127758;</span>
639
+ <div>
640
+ <p class="font-alt text-[11px] font-semibold text-capy-dark">Habitat</p>
641
+ <p class="font-body text-[10px] text-capy-dark/50">South American wetlands</p>
642
+ </div>
643
+ </div>
644
+ </div>
645
+ </div>
646
+
647
+ <!-- Cursor hint -->
648
+ <div class="cursor-hint" id="cursor-hint">
649
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
650
+ <path d="M12 2a4 4 0 0 0-4 4v2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2h-2V6a4 4 0 0 0-4-4z"/>
651
+ <circle cx="12" cy="15" r="1"/>
652
+ <path d="M8 11h8"/>
653
+ </svg>
654
+ <span>Drag to orbit &middot; Scroll to zoom &middot; Click capybara to interact</span>
655
+ </div>
656
+
657
+ </div>
658
+
659
+ <!-- Part info tooltip (follows cursor) -->
660
+ <div id="part-info" class="part-info">
661
+ <div class="glass px-3 py-2" style="border-radius:12px;">
662
+ <p id="part-info-text" class="font-alt text-xs font-semibold text-capy-dark">Head</p>
663
+ </div>
664
+ </div>
665
+
666
+ <script type="module">
667
+ import * as THREE from 'three';
668
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
669
+ import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
670
+ import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
671
+ import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
672
+
673
+ const canvas = document.getElementById('three-canvas');
674
+ const loadingScreen = document.getElementById('loading-screen');
675
+ const partInfo = document.getElementById('part-info');
676
+ const partInfoText = document.getElementById('part-info-text');
677
+
678
+ const scene = new THREE.Scene();
679
+ scene.background = new THREE.Color('#F2E6D8');
680
+ scene.fog = new THREE.Fog('#F2E6D8', 12, 28);
681
+
682
+ const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 100);
683
+ camera.position.set(5, 3.5, 7);
684
+
685
+ const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, powerPreference: 'high-performance' });
686
+ renderer.setSize(window.innerWidth, window.innerHeight);
687
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
688
+ renderer.shadowMap.enabled = true;
689
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
690
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
691
+ renderer.toneMappingExposure = 1.15;
692
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
693
+
694
+ // Post-processing (subtle bloom)
695
+ const composer = new EffectComposer(renderer);
696
+ composer.addPass(new RenderPass(scene, camera));
697
+ const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.15, 0.4, 0.85);
698
+ composer.addPass(bloomPass);
699
+
700
+ const controls = new OrbitControls(camera, canvas);
701
+ controls.enableDamping = true;
702
+ controls.dampingFactor = 0.06;
703
+ controls.minDistance = 4;
704
+ controls.maxDistance = 14;
705
+ controls.maxPolarAngle = Math.PI / 2.05;
706
+ controls.target.set(0, 0.8, 0);
707
+ controls.autoRotate = true;
708
+ controls.autoRotateSpeed = 0.6;
709
+
710
+ // ==================== LIGHTING ====================
711
+ const ambient = new THREE.AmbientLight(0xFFF5E8, 0.45);
712
+ scene.add(ambient);
713
+
714
+ const hemi = new THREE.HemisphereLight(0xE8DDD0, 0xB8C4A8, 0.55);
715
+ scene.add(hemi);
716
+
717
+ const dirLight = new THREE.DirectionalLight(0xFFF0D6, 1.6);
718
+ dirLight.position.set(5, 9, 5);
719
+ dirLight.castShadow = true;
720
+ dirLight.shadow.mapSize.set(2048, 2048);
721
+ dirLight.shadow.camera.near = 1;
722
+ dirLight.shadow.camera.far = 25;
723
+ dirLight.shadow.camera.left = -8;
724
+ dirLight.shadow.camera.right = 8;
725
+ dirLight.shadow.camera.top = 8;
726
+ dirLight.shadow.camera.bottom = -3;
727
+ dirLight.shadow.bias = -0.0005;
728
+ dirLight.shadow.radius = 3;
729
+ scene.add(dirLight);
730
+
731
+ const fillLight = new THREE.DirectionalLight(0xCCE8F0, 0.5);
732
+ fillLight.position.set(-4, 3, -3);
733
+ scene.add(fillLight);
734
+
735
+ const backLight = new THREE.DirectionalLight(0xFFE8D0, 0.4);
736
+ backLight.position.set(-3, 5, 7);
737
+ scene.add(backLight);
738
+
739
+ // ==================== MATERIALS ====================
740
+ const furMat = new THREE.MeshStandardMaterial({
741
+ color: 0xB88050,
742
+ roughness: 0.78,
743
+ metalness: 0.02,
744
+ });
745
+
746
+ const darkFurMat = new THREE.MeshStandardMaterial({
747
+ color: 0x7A5330,
748
+ roughness: 0.82,
749
+ metalness: 0.02,
750
+ });
751
+
752
+ const noseMat = new THREE.MeshStandardMaterial({
753
+ color: 0xC47A65,
754
+ roughness: 0.45,
755
+ metalness: 0.05,
756
+ });
757
+
758
+ const eyeMat = new THREE.MeshStandardMaterial({
759
+ color: 0x1A0F08,
760
+ roughness: 0.15,
761
+ metalness: 0.2,
762
+ });
763
+
764
+ const eyeShineMat = new THREE.MeshStandardMaterial({
765
+ color: 0xFFFFFF,
766
+ roughness: 0.1,
767
+ metalness: 0.1,
768
+ emissive: 0xFFFFFF,
769
+ emissiveIntensity: 0.4,
770
+ });
771
+
772
+ const toothMat = new THREE.MeshStandardMaterial({
773
+ color: 0xFFF8F0,
774
+ roughness: 0.35,
775
+ metalness: 0.0,
776
+ });
777
+
778
+ const grassMat = new THREE.MeshStandardMaterial({
779
+ color: 0x7BA872,
780
+ roughness: 0.92,
781
+ metalness: 0.0,
782
+ });
783
+
784
+ const waterMat = new THREE.MeshPhysicalMaterial({
785
+ color: 0x6EB5C2,
786
+ roughness: 0.1,
787
+ metalness: 0.05,
788
+ transmission: 0.45,
789
+ thickness: 1.2,
790
+ ior: 1.33,
791
+ transparent: true,
792
+ opacity: 0.7,
793
+ });
794
+
795
+ const rockMat = new THREE.MeshStandardMaterial({
796
+ color: 0x9A8A78,
797
+ roughness: 0.92,
798
+ metalness: 0.0,
799
+ });
800
+
801
+ const lilyMat = new THREE.MeshStandardMaterial({
802
+ color: 0x6B9E5E,
803
+ roughness: 0.7,
804
+ metalness: 0.0,
805
+ side: THREE.DoubleSide,
806
+ });
807
+
808
+ const lilyFlowerMat = new THREE.MeshStandardMaterial({
809
+ color: 0xF0D0C0,
810
+ roughness: 0.5,
811
+ metalness: 0.0,
812
+ });
813
+
814
+ const groundMat = new THREE.MeshStandardMaterial({
815
+ color: 0xD4C8A8,
816
+ roughness: 0.95,
817
+ metalness: 0.0,
818
+ });
819
+
820
+ // ==================== CAPYBARA ====================
821
+ const capyGroup = new THREE.Group();
822
+ const bodyParts = {};
823
+
824
+ // Body
825
+ const bodyGeo = new THREE.SphereGeometry(1.1, 22, 18);
826
+ bodyGeo.scale(1.0, 0.82, 1.35);
827
+ const body = new THREE.Mesh(bodyGeo, furMat.clone());
828
+ body.position.y = 1.25;
829
+ body.castShadow = true;
830
+ body.receiveShadow = true;
831
+ capyGroup.add(body);
832
+ bodyParts.body = body;
833
+
834
+ // Belly (subtle lighter patch)
835
+ const bellyGeo = new THREE.SphereGeometry(0.85, 16, 14);
836
+ bellyGeo.scale(0.9, 0.7, 1.1);
837
+ const bellyMat = furMat.clone();
838
+ bellyMat.color.setHex(0xC99A6B);
839
+ bellyMat.roughness = 0.85;
840
+ const belly = new THREE.Mesh(bellyGeo, bellyMat);
841
+ belly.position.set(0, 0.95, 0.15);
842
+ belly.castShadow = true;
843
+ belly.receiveShadow = true;
844
+ capyGroup.add(belly);
845
+
846
+ // Rump
847
+ const rumpGeo = new THREE.SphereGeometry(0.82, 18, 14);
848
+ rumpGeo.scale(1.02, 0.88, 1.08);
849
+ const rump = new THREE.Mesh(rumpGeo, furMat.clone());
850
+ rump.position.set(0, 1.35, -1.1);
851
+ rump.castShadow = true;
852
+ rump.receiveShadow = true;
853
+ capyGroup.add(rump);
854
+
855
+ // Head group
856
+ const headGroup = new THREE.Group();
857
+ headGroup.position.set(0, 1.95,