Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <title></title>
- <meta name="viewport" content="width=430px, user-scalable=no">
- <link href="https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700&family=Spectral+SC:wght@300;600&display=swap" rel="stylesheet">
- <style>
- :root {
- --bg: #0a0c12;
- --text: #f4f1e7;
- --gold: #d6b36a;
- --gold-soft: rgba(214, 179, 106, 0.15);
- --gold-strong: rgba(214, 179, 106, 0.35);
- --ease: cubic-bezier(.22,.61,.36,1);
- }
- * {
- box-sizing: border-box;
- margin: 0;
- padding: 0;
- }
- html, body {
- width: 100%;
- height: 100%;
- background: var(--bg);
- color: var(--text);
- font-family: 'Spectral SC', serif;
- overflow-x: hidden;
- overflow-y: auto;
- scroll-behavior: smooth;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-rendering: optimizeLegibility;
- }
- body::-webkit-scrollbar {
- width: 6px;
- }
- body::-webkit-scrollbar-thumb {
- background: linear-gradient(var(--gold), transparent);
- border-radius: 6px;
- }
- :focus-visible {
- outline: 2px solid var(--gold);
- outline-offset: 2px;
- border-radius: 4px;
- transition: outline-color .25s var(--ease);
- }
- .bg-container {
- position: fixed;
- inset: 0;
- overflow: hidden;
- z-index: 0;
- pointer-events: none;
- perspective: 800px;
- contain: strict;
- }
- .gyroscope {
- position: absolute;
- transform-style: preserve-3d;
- will-change: transform, opacity;
- filter: drop-shadow(0 0 4px rgba(214,179,106,0.25));
- transition: filter .3s var(--ease), opacity .6s var(--ease);
- opacity: 1;
- }
- .gyroscope:hover {
- filter: drop-shadow(0 0 8px rgba(214,179,106,0.6));
- }
- .gyroscope.fade-out {
- opacity: 0;
- }
- .ring {
- position: absolute;
- inset: 0;
- border: 1px solid rgba(214,179,106,0.1);
- border-radius: 50%;
- transform-style: preserve-3d;
- box-shadow: 0 0 4px rgba(214,179,106,0.15);
- transition: box-shadow .3s var(--ease);
- will-change: transform;
- }
- .ring:hover {
- box-shadow: 0 0 10px rgba(214,179,106,0.4);
- }
- .ring1 { animation: spinX 6s linear infinite; }
- .ring2 { animation: spinY 8s linear infinite; }
- .ring3 { animation: spinZ 10s linear infinite; }
- .ring4 { animation: spinX 12s linear infinite; }
- .ring5 { animation: spinY 14s linear infinite; }
- @keyframes spinX { from { transform: rotateX(0); } to { transform: rotateX(360deg); } }
- @keyframes spinY { from { transform: rotateY(0); } to { transform: rotateY(360deg); } }
- @keyframes spinZ { from { transform: rotateZ(0); } to { transform: rotateZ(360deg); } }
- .container {
- max-width: 430px;
- margin: 20px auto;
- padding: 20px;
- background: rgba(10, 12, 18, 0.85);
- backdrop-filter: blur(4px);
- border: 1px solid var(--gold-soft);
- border-radius: 20px;
- box-shadow: 0 0 40px var(--gold-soft), inset 0 0 25px rgba(214,179,106,0.08);
- position: relative;
- z-index: 2;
- transition: box-shadow .6s var(--ease);
- will-change: box-shadow;
- }
- .container:hover {
- box-shadow: 0 0 60px var(--gold-strong), inset 0 0 30px rgba(214,179,106,0.1);
- }
- .codex-title {
- font-family: 'Cinzel Decorative', cursive;
- text-align: center;
- font-size: 28px;
- color: var(--gold);
- text-shadow: 0 0 12px var(--gold-strong);
- margin-bottom: 16px;
- }
- .codex-img {
- width: 100%;
- height: auto;
- border-radius: 12px;
- box-shadow: 0 0 10px rgba(255,255,255,0.05);
- border: 1px solid rgba(255,255,255,0.06);
- margin-bottom: 10px;
- transition: transform .6s var(--ease), box-shadow .6s var(--ease);
- will-change: transform;
- transform: translateZ(0);
- }
- .codex-img:hover {
- transform: scale(1.02) translateZ(0);
- box-shadow: 0 0 16px rgba(255,255,255,0.08);
- }
- .codex-quote {
- font-style: italic;
- text-align: center;
- font-size: 13px;
- color: var(--gold);
- margin-bottom: 12px;
- padding: 0 10px;
- text-shadow: 0 0 6px rgba(214,179,106,0.2);
- }
- .tab-controls {
- display: flex;
- justify-content: space-around;
- margin: 12px 0;
- gap: 6px;
- }
- .tab {
- background: rgba(255,255,255,0.02);
- padding: 6px 12px;
- border-radius: 6px;
- color: var(--gold);
- cursor: pointer;
- font-size: 13px;
- border: 1px solid rgba(255,255,255,0.06);
- transition: background .3s var(--ease), color .3s var(--ease), box-shadow .3s var(--ease), transform .2s var(--ease);
- user-select: none;
- font-family: inherit;
- font-style: normal;
- font-weight: 600;
- will-change: transform;
- }
- .tab:hover, .tab.active {
- background: var(--gold-soft);
- color: var(--text);
- box-shadow: 0 0 10px var(--gold-strong);
- }
- .tab:active {
- transform: translateY(1px);
- }
- .tab-panel {
- display: none;
- margin-top: 14px;
- animation: fadeIn .6s var(--ease) forwards;
- }
- .tab-panel.active {
- display: block;
- }
- .section {
- margin-bottom: 14px;
- }
- .section-title {
- font-weight: 600;
- font-size: 13px;
- color: var(--gold);
- margin-bottom: 4px;
- }
- .section-content {
- font-size: 13px;
- line-height: 1.5;
- color: #eae7dd;
- }
- .scrollbox {
- max-height: 150px;
- overflow-y: auto;
- padding-right: 4px;
- border-left: 2px solid var(--gold-strong);
- padding-left: 8px;
- scroll-behavior: smooth;
- }
- .scrollbox::-webkit-scrollbar {
- width: 4px;
- }
- .scrollbox::-webkit-scrollbar-thumb {
- background: var(--gold);
- border-radius: 3px;
- }
- .audio-controls {
- text-align: center;
- margin-top: 14px;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 10px;
- opacity: .3;
- transition: opacity .3s var(--ease);
- }
- .audio-controls:hover {
- opacity: 1;
- }
- .volume-slider {
- width: 100px;
- accent-color: var(--gold);
- transition: filter .25s var(--ease);
- filter: drop-shadow(0 0 0 rgba(0,0,0,0));
- }
- .volume-slider:focus-visible {
- filter: drop-shadow(0 0 6px rgba(214,179,106,0.35));
- }
- .audio-button {
- cursor: pointer;
- font-size: 14px;
- background: none;
- color: var(--gold);
- border: none;
- font-family: inherit;
- font-style: normal;
- font-weight: 600;
- transition: transform .2s var(--ease), text-shadow .3s var(--ease);
- }
- .audio-button:active {
- transform: scale(.98);
- }
- @keyframes fadeIn {
- 0% { opacity: 0; transform: translateY(10px); }
- 100% { opacity: 1; transform: translateY(0); }
- }
- @media (prefers-reduced-motion: reduce) {
- .ring1, .ring2, .ring3, .ring4, .ring5 { animation: none !important; }
- .tab-panel { animation: none; }
- .codex-img { transition: none; }
- .container { transition: none; }
- .audio-controls { transition: none; }
- }
- .volume-slider::-webkit-slider-runnable-track {
- height: 4px;
- background: linear-gradient(to right, var(--gold-strong), rgba(255,255,255,0.06));
- border-radius: 999px;
- }
- .volume-slider::-webkit-slider-thumb {
- -webkit-appearance: none;
- appearance: none;
- width: 14px;
- height: 14px;
- border-radius: 50%;
- background: var(--gold);
- border: 1px solid rgba(0,0,0,0.25);
- margin-top: -5px;
- box-shadow: 0 0 8px var(--gold-strong);
- }
- .volume-slider::-moz-range-track {
- height: 4px;
- background: linear-gradient(to right, var(--gold-strong), rgba(255,255,255,0.06));
- border-radius: 999px;
- }
- .volume-slider::-moz-range-thumb {
- width: 14px;
- height: 14px;
- border-radius: 50%;
- background: var(--gold);
- border: 1px solid rgba(0,0,0,0.25);
- box-shadow: 0 0 8px var(--gold-strong);
- }
- .volume-slider::-ms-track {
- height: 4px;
- background: transparent;
- border-color: transparent;
- color: transparent;
- }
- .volume-slider::-ms-fill-lower, .volume-slider::-ms-fill-upper {
- background: linear-gradient(to right, var(--gold-strong), rgba(255,255,255,0.06));
- border-radius: 999px;
- }
- .volume-slider::-ms-thumb {
- width: 14px;
- height: 14px;
- border-radius: 50%;
- background: var(--gold);
- border: 1px solid rgba(0,0,0,0.25);
- box-shadow: 0 0 8px var(--gold-strong);
- }
- #overview .section-content strong {
- color: var(--gold);
- text-shadow: 0 0 4px var(--gold-strong);
- letter-spacing: 0.3px;
- font-variant-caps: small-caps;
- }
- </style>
- </head>
- <body>
- <div class="bg-container" id="bg-container" aria-hidden="true"></div>
- <div class="container">
- <h1 class="codex-title">Unnamed Soul</h1>
- <img class="codex-img" src="(IMAGE_PLACEHOLDER)" loading="lazy" decoding="async">
- <p class="codex-quote">"..."</p>
- <div class="tab-controls" role="tablist" aria-label="Profile sections">
- <button class="tab active" role="tab" aria-selected="true" aria-controls="overview" id="tab-overview" tabindex="0" data-tab="overview">Overview</button>
- <button class="tab" role="tab" aria-selected="false" aria-controls="history" id="tab-history" tabindex="-1" data-tab="history">History</button>
- <button class="tab" role="tab" aria-selected="false" aria-controls="achievements" id="tab-achievements" tabindex="-1" data-tab="achievements">Achievements</button>
- </div>
- <section class="tab-panel active" id="overview" role="tabpanel" aria-labelledby="tab-overview">
- <div class="section">
- <div class="section-title">Codex Identification</div>
- <div class="section-content">
- <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
- <div><strong>Race</strong><br>(RACE_PLACEHOLDER)</div>
- <div><strong>Class</strong><br>(CLASS_PLACEHOLDER)</div>
- <div><strong>Age</strong><br>(AGE_PLACEHOLDER)</div>
- <div><strong>Height</strong><br>(HEIGHT_PLACEHOLDER)</div>
- <div><strong>Weight</strong><br>(WEIGHT_PLACEHOLDER)</div>
- <div><strong>Eye Color</strong><br>(EYE_COLOR_PLACEHOLDER)</div>
- <div style="grid-column: 1 / -1; text-align: center;"><strong>Hair Color</strong><br>(HAIR_COLOR_PLACEHOLDER)</div>
- </div>
- </div>
- </div>
- <hr style="border: 0; border-top: 1px solid var(--gold-soft); margin: 14px 0;">
- <div class="section">
- <div class="section-title">Affiliation</div>
- <div class="section-content">
- <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
- <div><strong>Order</strong><br>(ORDER_PLACEHOLDER)</div>
- <div><strong>Division</strong><br>(DIVISION_PLACEHOLDER)</div>
- </div>
- <div style="text-align: center; margin-top: 10px;"><strong>Current Rank</strong><br>(CURRENT_RANK_PLACEHOLDER)</div>
- </div>
- </div>
- </section>
- <section class="tab-panel" id="history" role="tabpanel" aria-labelledby="tab-history">
- <div class="section">
- <div class="section-title">Recorded Past</div>
- <div class="section-content scrollbox">
- <p>(HISTORY_PLACEHOLDER)</p>
- </div>
- </div>
- </section>
- <section class="tab-panel" id="achievements" role="tabpanel" aria-labelledby="tab-achievements">
- <div class="section">
- <div class="section-title">Recognized Achievements</div>
- <div class="section-content scrollbox">
- <ul style="padding-left: 18px;">
- <li>(ACHIEVEMENT_1)</li>
- <li>(ACHIEVEMENT_2)</li>
- <li>(ACHIEVEMENT_3)</li>
- <li>(ACHIEVEMENT_4)</li>
- </ul>
- </div>
- </div>
- </section>
- <div class="audio-controls">
- <button class="audio-button" id="audio-toggle" aria-label="Play or pause ambient music">▶</button>
- <input type="range" min="0" max="1" step="0.01" class="volume-slider" id="volume" aria-label="Volume" value="0.4">
- </div>
- </div>
- <audio id="ambient" preload="auto" loop>
- <source src="https://od.lk/s/ODBfNTg4NTM5NTFf/The%20Night%20Unfurls.mp3" type="audio/mpeg">
- </audio>
- <script>
- const audio = document.getElementById('ambient');
- const volInput = document.getElementById('volume');
- const toggleBtn = document.getElementById('audio-toggle');
- const savedVol = localStorage.getItem('codex_volume');
- if (savedVol !== null) volInput.value = savedVol;
- let volumeTween = null;
- function reflectBtn() { toggleBtn.textContent = audio.paused ? '▶' : '⏸'; }
- function rampVolume(target, ms) {
- if (volumeTween) cancelAnimationFrame(volumeTween.raf);
- const start = audio.volume;
- const delta = target - start;
- const startTime = performance.now();
- function step(now) {
- const t = Math.min(1, (now - startTime) / ms);
- audio.volume = start + delta * (t * (2 - t));
- if (t < 1) volumeTween = { raf: requestAnimationFrame(step) }; else volumeTween = null;
- }
- volumeTween = { raf: requestAnimationFrame(step) };
- }
- async function tryAutoplay() {
- audio.volume = Number(volInput.value);
- try { await audio.play(); } catch (_) {}
- reflectBtn();
- }
- function toggleAudio() {
- if (audio.paused) {
- rampVolume(Number(volInput.value), 120);
- audio.play();
- } else {
- rampVolume(0, 120);
- setTimeout(() => { audio.pause(); reflectBtn(); audio.volume = Number(volInput.value); }, 130);
- }
- reflectBtn();
- }
- function setVolume(value) {
- const v = Number(value);
- audio.volume = v;
- localStorage.setItem('codex_volume', value);
- }
- toggleBtn.addEventListener('click', toggleAudio, { passive: true });
- volInput.addEventListener('input', e => setVolume(e.target.value), { passive: true });
- document.addEventListener('visibilitychange', () => {
- if (document.hidden && !audio.paused) {
- audio.pause();
- reflectBtn();
- }
- }, { passive: true });
- window.addEventListener('load', tryAutoplay, { passive: true });
- const tabs = Array.from(document.querySelectorAll('[role="tab"]'));
- const panels = Array.from(document.querySelectorAll('[role="tabpanel"]'));
- function activateTab(tab) {
- tabs.forEach(t => {
- const selected = t === tab;
- t.classList.toggle('active', selected);
- t.setAttribute('aria-selected', selected);
- t.tabIndex = selected ? 0 : -1;
- });
- panels.forEach(p => {
- const isTarget = p.id === tab.getAttribute('aria-controls');
- p.classList.toggle('active', isTarget);
- p.setAttribute('aria-hidden', String(!isTarget));
- if (isTarget) {
- p.style.animation = 'none';
- void p.offsetWidth;
- p.style.animation = '';
- }
- });
- tab.focus();
- }
- tabs.forEach(tab => {
- tab.addEventListener('click', () => activateTab(tab), { passive: true });
- tab.addEventListener('keydown', e => {
- const idx = tabs.indexOf(tab);
- if (e.key === 'ArrowRight') {
- e.preventDefault();
- activateTab(tabs[(idx + 1) % tabs.length]);
- } else if (e.key === 'ArrowLeft') {
- e.preventDefault();
- activateTab(tabs[(idx - 1 + tabs.length) % tabs.length]);
- } else if (e.key === 'Home') {
- e.preventDefault();
- activateTab(tabs[0]);
- } else if (e.key === 'End') {
- e.preventDefault();
- activateTab(tabs[tabs.length - 1]);
- } else if (e.key === 'Enter' || e.key === ' ') {
- e.preventDefault();
- activateTab(tab);
- }
- });
- });
- const container = document.getElementById('bg-container');
- const rmQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
- let reducedMotion = rmQuery.matches;
- let gyros = [];
- const POOL = [];
- const MAX_GYROS = 60;
- const SPAWN_INTERVAL = 260;
- let lastSpawn = 0;
- let animRAF = null;
- rmQuery.addEventListener?.('change', e => {
- reducedMotion = e.matches;
- if (reducedMotion) clearScene();
- });
- function makeGyroEl() {
- const el = document.createElement('div');
- el.className = 'gyroscope';
- return el;
- }
- function buildGyro(el, rings) {
- el.replaceChildren();
- let parent = el;
- for (let i = 1; i <= rings; i++) {
- const ring = document.createElement('div');
- ring.className = `ring ring${i}`;
- parent.appendChild(ring);
- parent = ring;
- }
- }
- function spawnGyro() {
- if (reducedMotion || gyros.length >= MAX_GYROS) return;
- const size = 15 + Math.random() * 15;
- const rings = 2 + Math.floor(Math.random() * 4);
- const x = Math.random() * window.innerWidth;
- const y = window.innerHeight + 30;
- const el = POOL.pop() || makeGyroEl();
- buildGyro(el, rings);
- el.style.width = size + 'px';
- el.style.height = size + 'px';
- container.appendChild(el);
- gyros.push({ el, x, y, vx: 0, vy: -0.3 - Math.random() * 0.3, size, alive: true });
- }
- function recycle(g) {
- g.alive = false;
- g.el.classList.add('fade-out');
- setTimeout(() => {
- g.el.remove();
- g.el.classList.remove('fade-out');
- POOL.push(g.el);
- }, 250);
- }
- function clearScene() {
- gyros.forEach(g => recycle(g));
- gyros = [];
- }
- function tick(now) {
- animRAF = requestAnimationFrame(tick);
- if (document.hidden || reducedMotion) return;
- if (!lastSpawn) lastSpawn = now;
- if (now - lastSpawn > SPAWN_INTERVAL) {
- spawnGyro();
- lastSpawn = now;
- }
- for (let i = gyros.length - 1; i >= 0; i--) {
- const g = gyros[i];
- if (!g.alive) {
- gyros.splice(i, 1);
- continue;
- }
- g.y += g.vy;
- g.x += g.vx * 0.98;
- g.el.style.transform = `translate3d(${g.x}px, ${g.y}px, 0)`;
- if (g.y + g.size <= -50) {
- recycle(g);
- gyros.splice(i, 1);
- }
- }
- }
- function start() {
- if (!animRAF) animRAF = requestAnimationFrame(tick);
- }
- function stop() {
- if (animRAF) cancelAnimationFrame(animRAF);
- animRAF = null;
- }
- window.addEventListener('resize', () => { clearScene(); }, { passive: true });
- document.addEventListener('visibilitychange', () => {
- if (document.hidden) stop();
- else start();
- }, { passive: true });
- start();
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment