Initial commit — Singular Particular Space v1
Homepage (site/index.html): integration-v14 promoted, Writings section integrated with 33 pieces clustered by type (stories/essays/miscellany), Writings welcome lightbox, content frame at 98% opacity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,386 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!--
|
||||
Integration v7 — THE NIGHT MARKET: FINAL DESCENT — 2026-03-26
|
||||
AUTHOR: Gemini (Master Designer)
|
||||
|
||||
PARALLAX & FLOW:
|
||||
- Stars & Grid (Back): Fixed-ish, drifting UP slowly (0.1x).
|
||||
- Skyline (Mid): Rises gracefully from the bottom.
|
||||
- Fading: Grid fades first, then Stars, as you descend into the city.
|
||||
- Aesthetics: Buildings 25% darker (#040712), lush vines, dynamic grid pulses.
|
||||
- Widescreen: Ultra-dense skyline (100 buildings) with clustered nav.
|
||||
-->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Singular Particular Space</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Space+Grotesk:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-void: #04060b;
|
||||
--bg-deep: #040712; /* 25% darker */
|
||||
--bg-warm: #0d1320;
|
||||
--fire-amber: #e8943a;
|
||||
--fire-coral: #d4654a;
|
||||
--neon-green: #32dc8c;
|
||||
--neon-teal: #2ac4b3;
|
||||
--orchid: #c558d9;
|
||||
--mint-glow: #86efac;
|
||||
--fairy-pink: #f472b6;
|
||||
--phosphor: #00ff41;
|
||||
--text-warm: #e8d5b8;
|
||||
--text-muted: #6a7a8a;
|
||||
}
|
||||
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html { scroll-behavior: auto; overflow-x: hidden; }
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg-void);
|
||||
color: var(--text-warm);
|
||||
min-height: 200vh; /* Enable scroll for transition */
|
||||
}
|
||||
|
||||
body.content-mode { overflow-y: auto; }
|
||||
|
||||
/* ── CRT Scanlines ── */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0, 0, 0, 0.04) 2px, rgba(0, 0, 0, 0.04) 4px);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* ── Star Zone (The Fixed-ish Back) ── */
|
||||
#star-zone {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100vh;
|
||||
z-index: 1;
|
||||
background: radial-gradient(ellipse at 50% 40%, #090d1c 0%, var(--bg-void) 100%);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#nebula-canvas, #star-canvas, #grid-canvas {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
#grid-canvas {
|
||||
height: 45vh;
|
||||
top: auto; bottom: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* ── Star Nodes ── */
|
||||
.star-node {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
background: none; border: none; outline: none;
|
||||
}
|
||||
|
||||
.star-visual {
|
||||
position: relative;
|
||||
width: 40px; height: 40px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
|
||||
.star-dot {
|
||||
width: 7px; height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--text-muted);
|
||||
box-shadow: 0 0 6px rgba(255,255,255,0.2);
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.star-label {
|
||||
font-size: clamp(12px, 2vw, 16px);
|
||||
color: var(--text-muted);
|
||||
opacity: 0;
|
||||
transition: all 200ms ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.star-node:hover .star-label, .star-node.current .star-label { opacity: 1; color: var(--text-warm); }
|
||||
.star-node:hover .star-dot { width: 20px; height: 20px; background: var(--fire-amber) !important; box-shadow: 0 0 12px var(--fire-amber); }
|
||||
.star-node.current .star-dot { width: 40px; height: 40px; background: var(--fire-amber) !important; box-shadow: 0 0 20px var(--fire-amber); }
|
||||
|
||||
/* Per-star colors */
|
||||
.star-node[data-star="writings"] .star-dot { background: #a0c4ff; }
|
||||
.star-node[data-star="videos"] .star-dot { background: #d4654a; }
|
||||
.star-node[data-star="music"] .star-dot { background: #2ac4b3; }
|
||||
.star-node[data-star="images"] .star-dot { background: #86efac; }
|
||||
.star-node[data-star="playlists"] .star-dot { background: #ffcf40; }
|
||||
.star-node[data-star="watchlists"] .star-dot { background: #c558d9; }
|
||||
.star-node[data-star="toolsntoys"] .star-dot { background: #f472b6; }
|
||||
.star-node[data-star="creatorlists"] .star-dot { background: #c4a24a; }
|
||||
|
||||
/* ── Transition Zone (The Rising Mid) ── */
|
||||
#transition-zone {
|
||||
position: relative;
|
||||
width: 100%; height: 100vh;
|
||||
margin-top: 100vh; /* Sits below the star zone */
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#skyline {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding-bottom: 5vh;
|
||||
}
|
||||
|
||||
.building {
|
||||
background: var(--bg-deep);
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(232, 148, 58, 0.1);
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.vine {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
background: var(--mint-glow);
|
||||
opacity: 0.2;
|
||||
box-shadow: 0 0 4px var(--mint-glow);
|
||||
animation: vine-glow 4s infinite;
|
||||
}
|
||||
.vine.orchid { background: var(--orchid); box-shadow: 0 0 4px var(--orchid); animation-delay: 2s; }
|
||||
|
||||
@keyframes vine-glow { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.4; } }
|
||||
|
||||
.billboard-nav {
|
||||
position: absolute;
|
||||
top: -2px; left: 50%;
|
||||
transform: translate(-50%, -100%);
|
||||
background: rgba(4, 6, 11, 0.95);
|
||||
border: 1px solid var(--neon-teal);
|
||||
color: var(--neon-teal);
|
||||
padding: 4px 10px;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
pointer-events: auto;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* ── Content Zone ── */
|
||||
#content-zone {
|
||||
position: relative;
|
||||
width: 100%; min-height: 100vh;
|
||||
background: var(--bg-warm);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#content-frame {
|
||||
width: 100%; height: 100vh;
|
||||
border: none; background: var(--bg-warm);
|
||||
opacity: 0; transition: opacity 0.5s;
|
||||
}
|
||||
#content-frame.loaded { opacity: 1; }
|
||||
|
||||
#hud {
|
||||
position: fixed; top: 15px; right: 15px; z-index: 100;
|
||||
background: rgba(4,6,11,0.9); border: 1px solid rgba(0,255,65,0.2);
|
||||
padding: 8px 12px; font-family: monospace; color: var(--phosphor);
|
||||
}
|
||||
#back-btn { background: none; border: none; color: inherit; cursor: pointer; }
|
||||
#back-btn::before { content: '> '; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="star-zone">
|
||||
<canvas id="nebula-canvas"></canvas>
|
||||
<canvas id="star-canvas"></canvas>
|
||||
<canvas id="grid-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="transition-zone">
|
||||
<div id="skyline"></div>
|
||||
</div>
|
||||
|
||||
<div id="content-zone">
|
||||
<iframe id="content-frame"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="hud">
|
||||
<button id="back-btn">STARS</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STARS = [
|
||||
{ id: 'writings', label: 'Writings', sign: '文', x: 25, y: 18 },
|
||||
{ id: 'videos', label: 'Videos', sign: '映', x: 68, y: 15 },
|
||||
{ id: 'music', label: 'Music', sign: '♬', x: 12, y: 42 },
|
||||
{ id: 'images', label: 'Images', sign: '絵', x: 55, y: 35 },
|
||||
{ id: 'playlists', label: 'Playlists', sign: '≡', x: 78, y: 48 },
|
||||
{ id: 'watchlists', label: 'Watchlists', sign: '視', x: 22, y: 65 },
|
||||
{ id: 'toolsntoys', label: 'ToolsnToys', sign: '⚙', x: 50, y: 72 },
|
||||
{ id: 'creatorlists', label: 'Creatorlists', sign: '創', x: 75, y: 70 }
|
||||
];
|
||||
|
||||
const starCanvas = document.getElementById('star-canvas');
|
||||
const nebulaCanvas = document.getElementById('nebula-canvas');
|
||||
const gridCanvas = document.getElementById('grid-canvas');
|
||||
const transitionZone = document.getElementById('transition-zone');
|
||||
const skyline = document.getElementById('skyline');
|
||||
const starZone = document.getElementById('star-zone');
|
||||
|
||||
// ── Syncronized Parallax ──
|
||||
function updateParallax() {
|
||||
const scrollY = window.scrollY || window.pageYOffset;
|
||||
const vh = window.innerHeight;
|
||||
const progress = Math.min(scrollY / vh, 1);
|
||||
|
||||
// 1. Background Layers (Stars/Grid) - Move SLOWLY (10% speed)
|
||||
const bgTranslate = -scrollY * 0.1;
|
||||
starCanvas.style.transform = `translateY(${bgTranslate}px)`;
|
||||
nebulaCanvas.style.transform = `translateY(${bgTranslate}px)`;
|
||||
gridCanvas.style.transform = `translateY(${bgTranslate}px)`;
|
||||
|
||||
// 2. Fading Sequence (Grid first, then Stars)
|
||||
gridCanvas.style.opacity = Math.max(0, 1 - progress * 2.5); // Fades out by 40% scroll
|
||||
starCanvas.style.opacity = Math.max(0, 1 - progress * 1.2); // Fades out by 85% scroll
|
||||
nebulaCanvas.style.opacity = Math.max(0, 1 - progress * 1.5);
|
||||
|
||||
// 3. Skyline (Mid) - Rises gracefully as you scroll
|
||||
// Since transition-zone is already moving with scroll, we just tweak its relative position
|
||||
const skyRise = -scrollY * 0.2;
|
||||
skyline.style.transform = `translateY(${skyRise}px)`;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', updateParallax, { passive: true });
|
||||
|
||||
// ── Starfield Drift ──
|
||||
let bgStars = [];
|
||||
function initStars() {
|
||||
const w = window.innerWidth, h = window.innerHeight;
|
||||
starCanvas.width = w; starCanvas.height = h;
|
||||
bgStars = Array.from({length: 300}, () => ({
|
||||
x: Math.random() * w, y: Math.random() * h,
|
||||
r: Math.random() * 2,
|
||||
dx: (Math.random() - 0.5) * 0.05,
|
||||
dy: (Math.random() - 0.5) * 0.05,
|
||||
o: 0.1 + Math.random() * 0.5
|
||||
}));
|
||||
}
|
||||
|
||||
function drawStars() {
|
||||
const ctx = starCanvas.getContext('2d');
|
||||
ctx.clearRect(0,0,starCanvas.width, starCanvas.height);
|
||||
bgStars.forEach(s => {
|
||||
s.x += s.dx; s.y += s.dy;
|
||||
if (s.x < 0) s.x = starCanvas.width; if (s.x > starCanvas.width) s.x = 0;
|
||||
if (s.y < 0) s.y = starCanvas.height; if (s.y > starCanvas.height) s.y = 0;
|
||||
ctx.fillStyle = `rgba(232, 213, 184, ${s.o})`;
|
||||
ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, 6.28); ctx.fill();
|
||||
});
|
||||
requestAnimationFrame(drawStars);
|
||||
}
|
||||
|
||||
// ── Data Pulse Grid ──
|
||||
function drawGrid(time) {
|
||||
const ctx = gridCanvas.getContext('2d');
|
||||
const w = gridCanvas.width = gridCanvas.offsetWidth;
|
||||
const h = gridCanvas.height = gridCanvas.offsetHeight;
|
||||
ctx.clearRect(0,0,w,h);
|
||||
const pulsePos = (time * 0.05) % 100;
|
||||
|
||||
for(let i=0; i<15; i++) {
|
||||
let s = i/14;
|
||||
let y = h * (s*s);
|
||||
ctx.strokeStyle = `rgba(42, 196, 179, ${0.04 + s*0.15})`;
|
||||
if (Math.abs(s*100 - pulsePos) < 5) ctx.strokeStyle = `rgba(232, 148, 58, 0.35)`;
|
||||
ctx.lineWidth = 1.2;
|
||||
ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(w, y); ctx.stroke();
|
||||
}
|
||||
requestAnimationFrame(drawGrid);
|
||||
}
|
||||
|
||||
// ── Skyline ──
|
||||
function buildSkyline() {
|
||||
const container = document.getElementById('skyline');
|
||||
container.innerHTML = '';
|
||||
const vw = window.innerWidth, vh = window.innerHeight;
|
||||
const count = 100; // High density
|
||||
const clusterStart = Math.floor(count/2) - 4;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const b = document.createElement('div');
|
||||
b.className = 'building';
|
||||
b.style.width = (vw < 768 ? 30 : 60) + Math.random()*50 + 'px';
|
||||
b.style.height = (vh * 0.15 + Math.random() * (vh * 0.55)) + 'px';
|
||||
|
||||
if(Math.random() > 0.4) {
|
||||
const v = document.createElement('div');
|
||||
v.className = 'vine' + (Math.random() > 0.5 ? ' orchid' : '');
|
||||
v.style.left = '30%'; v.style.top = '10%'; v.style.height = '30%';
|
||||
b.appendChild(v);
|
||||
}
|
||||
|
||||
if (i >= clusterStart && i < clusterStart + 8) {
|
||||
const star = STARS[i - clusterStart];
|
||||
const link = document.createElement('a');
|
||||
link.className = 'billboard-nav';
|
||||
link.textContent = star.sign;
|
||||
link.href = '#';
|
||||
link.onclick = (e) => { e.preventDefault(); selectStar(STARS.indexOf(star)); };
|
||||
b.appendChild(link);
|
||||
}
|
||||
container.appendChild(b);
|
||||
}
|
||||
}
|
||||
|
||||
function selectStar(idx) {
|
||||
const frame = document.getElementById('content-frame');
|
||||
frame.classList.remove('loaded');
|
||||
frame.srcdoc = `<html><body style="background:#0d1320;color:#e8d5b8;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;">
|
||||
<p>Entering ${STARS[idx].label}...</p></body></html>`;
|
||||
setTimeout(() => frame.classList.add('loaded'), 500);
|
||||
window.scrollTo({ top: document.getElementById('content-zone').offsetTop, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
document.getElementById('back-btn').onclick = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
STARS.forEach((s, i) => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'star-node';
|
||||
btn.setAttribute('data-star', s.id);
|
||||
btn.style.left = s.x + '%'; btn.style.top = s.y + '%';
|
||||
btn.innerHTML = `<div class="star-visual"><span class="star-dot"></span></div><span class="star-label">${s.label}</span>`;
|
||||
btn.onclick = () => selectStar(i);
|
||||
starZone.appendChild(btn);
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => { initStars(); buildSkyline(); });
|
||||
initStars(); buildSkyline(); drawStars(); requestAnimationFrame(drawGrid);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,417 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!--
|
||||
Integration v7 — THE NIGHT MARKET: MERGED MASTERY — 2026-03-26
|
||||
AUTHOR: Gemini (Master Designer) & Sonnet (Full-stack Integration)
|
||||
|
||||
THE MOTION FLOW:
|
||||
- Stars & Grid (Locked Back): Recede UP slowly (0.1x relative speed).
|
||||
- Sequence Fading: Grid fades by 40% scroll, Stars by 85% scroll.
|
||||
- Skyline Ascent: Rises quickly (0.7x relative speed) into the sky.
|
||||
- 8px Gap Constraint: Grid pinned to star-zone base; flush alignment.
|
||||
|
||||
THE AESTHETIC (Vaporwave Mad Max Rainforest):
|
||||
- 25% Darker Buildings (#050810).
|
||||
- Procedural Bioluminescent Overgrowth (Mint/Orchid).
|
||||
- Holographic Glitch Glyphs (文映♬絵≡視⚙創).
|
||||
- Scavenged Matrix HUD ([ SYSTEM ] header, phosphor green).
|
||||
- CRT Ghost (0.04 opacity).
|
||||
|
||||
THE MECHANICS:
|
||||
- Smooth cubic descent/ascent.
|
||||
- Keyboard spatial navigation (arrow keys).
|
||||
- Visited star tracking (localStorage).
|
||||
- Throttled 20fps RAF for performance.
|
||||
-->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Singular Particular Space</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Space+Grotesk:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-void: #04060b;
|
||||
--bg-deep: #050810; /* 25% Darker */
|
||||
--bg-warm: #0d1320;
|
||||
--fire-amber: #e8943a;
|
||||
--fire-coral: #d4654a;
|
||||
--neon-green: #32dc8c;
|
||||
--neon-teal: #2ac4b3;
|
||||
--orchid: #c558d9;
|
||||
--mint-glow: #86efac;
|
||||
--fairy-pink: #f472b6;
|
||||
--phosphor: #00ff41;
|
||||
--text-warm: #e8d5b8;
|
||||
--text-muted: #6a7a8a;
|
||||
}
|
||||
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html { scroll-behavior: auto; overflow-x: hidden; }
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, sans-serif;
|
||||
background: var(--bg-void);
|
||||
color: var(--text-warm);
|
||||
min-height: 200vh;
|
||||
}
|
||||
body.content-mode { overflow-y: auto; }
|
||||
|
||||
/* ── CRT Scanline Overlay ── */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0, 0, 0, 0.04) 2px, rgba(0, 0, 0, 0.04) 4px);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* ── Zone 1: Star Map (The Receding Back) ── */
|
||||
#star-zone {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100vh;
|
||||
z-index: 1;
|
||||
background: radial-gradient(ellipse at 50% 40%, #090d1c 0%, var(--bg-void) 100%);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#nebula-canvas, #star-canvas, #grid-canvas {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
#grid-canvas {
|
||||
height: 45vh;
|
||||
top: auto; bottom: 0; /* Flush with bottom */
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* ── Star Nodes ── */
|
||||
.star-node {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
background: none; border: none; outline: none;
|
||||
}
|
||||
|
||||
.star-visual {
|
||||
position: relative;
|
||||
width: 40px; height: 40px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
|
||||
.star-dot {
|
||||
width: 7px; height: 7px;
|
||||
border-radius: 50%;
|
||||
transition: all 150ms ease;
|
||||
box-shadow: 0 0 6px rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
.star-label {
|
||||
font-size: clamp(12px, 2vw, 16px);
|
||||
color: var(--text-muted);
|
||||
opacity: 0;
|
||||
transition: all 200ms ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.star-node:hover .star-label, .star-node.current .star-label { opacity: 1; color: var(--text-warm); }
|
||||
|
||||
/* Personality Colors */
|
||||
.star-node[data-star="writings"] .star-dot { background: #a0c4ff; }
|
||||
.star-node[data-star="videos"] .star-dot { background: #d4654a; }
|
||||
.star-node[data-star="music"] .star-dot { background: #2ac4b3; }
|
||||
.star-node[data-star="images"] .star-dot { background: #86efac; }
|
||||
.star-node[data-star="playlists"] .star-dot { background: #ffcf40; }
|
||||
.star-node[data-star="watchlists"] .star-dot { background: #c558d9; }
|
||||
.star-node[data-star="toolsntoys"] .star-dot { background: #f472b6; }
|
||||
.star-node[data-star="creatorlists"] .star-dot { background: #c4a24a; }
|
||||
|
||||
/* Bloom Effect */
|
||||
.star-node:hover .star-dot { width: 20px; height: 20px; background: var(--fire-amber) !important; box-shadow: 0 0 12px var(--fire-amber); }
|
||||
.star-node.current .star-dot { width: 40px; height: 40px; background: var(--fire-amber) !important; box-shadow: 0 0 20px var(--fire-amber); }
|
||||
|
||||
/* ── Zone 2: Transition (The Rising Skyline) ── */
|
||||
#transition-zone {
|
||||
position: relative;
|
||||
width: 100%; height: 100vh;
|
||||
margin-top: 100vh;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#skyline {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding-bottom: 2vh;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.building {
|
||||
background: var(--bg-deep);
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(232, 148, 58, 0.12);
|
||||
margin: 0 1px;
|
||||
}
|
||||
|
||||
.vine {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
background: var(--mint-glow);
|
||||
opacity: 0.2;
|
||||
box-shadow: 0 0 4px var(--mint-glow);
|
||||
animation: vine-breathe 4s infinite;
|
||||
}
|
||||
.vine.orchid { background: var(--orchid); box-shadow: 0 0 4px var(--orchid); animation-delay: 2s; }
|
||||
|
||||
@keyframes vine-breathe { 0%, 100% { opacity: 0.15; height: 30%; } 50% { opacity: 0.4; height: 45%; } }
|
||||
|
||||
.billboard-nav {
|
||||
position: absolute;
|
||||
top: -2px; left: 50%;
|
||||
transform: translate(-50%, -100%);
|
||||
background: rgba(4, 6, 11, 0.95);
|
||||
border: 1px solid var(--neon-teal);
|
||||
color: var(--neon-teal);
|
||||
padding: 4px 10px;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
pointer-events: auto;
|
||||
z-index: 10;
|
||||
animation: glitch 12s infinite;
|
||||
}
|
||||
|
||||
@keyframes glitch {
|
||||
0%, 94%, 100% { transform: translate(-50%, -100%) skew(0deg); }
|
||||
95% { transform: translate(-52%, -101%) skew(4deg); color: var(--fire-coral); }
|
||||
97% { transform: translate(-48%, -99%) skew(-3deg); color: var(--orchid); }
|
||||
}
|
||||
|
||||
/* ── Zone 3: Content ── */
|
||||
#content-zone {
|
||||
position: relative;
|
||||
width: 100%; min-height: 100vh;
|
||||
background: var(--bg-warm);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#content-frame {
|
||||
width: 100%; height: 100vh;
|
||||
border: none; background: var(--bg-warm);
|
||||
opacity: 0; transition: opacity 0.4s;
|
||||
}
|
||||
#content-frame.loaded { opacity: 1; }
|
||||
|
||||
/* ── HUD ── */
|
||||
#hud {
|
||||
position: fixed; top: 15px; right: 15px; z-index: 100;
|
||||
background: rgba(4, 6, 11, 0.9); border: 1px solid rgba(0, 255, 65, 0.15);
|
||||
padding: 10px 14px; font-family: monospace;
|
||||
}
|
||||
#hud::before { content: '[ SYSTEM ]'; font-size: 8px; color: rgba(0,255,65,0.4); display: block; margin-bottom: 4px; }
|
||||
#back-btn { background: none; border: none; color: var(--phosphor); cursor: pointer; font-size: 12px; }
|
||||
#back-btn::before { content: '> '; }
|
||||
#back-btn::after { content: '_'; animation: cursor-blink 1s step-end infinite; }
|
||||
@keyframes cursor-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="star-zone">
|
||||
<canvas id="nebula-canvas"></canvas>
|
||||
<canvas id="star-canvas"></canvas>
|
||||
<canvas id="grid-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="transition-zone">
|
||||
<div id="skyline"></div>
|
||||
</div>
|
||||
|
||||
<div id="content-zone">
|
||||
<iframe id="content-frame"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="hud">
|
||||
<button id="back-btn">STARS</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STARS = [
|
||||
{ id: 'writings', label: 'Writings', sign: '文', x: 25, y: 18 },
|
||||
{ id: 'videos', label: 'Videos', sign: '映', x: 68, y: 15 },
|
||||
{ id: 'music', label: 'Music', sign: '♬', x: 12, y: 42 },
|
||||
{ id: 'images', label: 'Images', sign: '絵', x: 55, y: 35 },
|
||||
{ id: 'playlists', label: 'Playlists', sign: '≡', x: 78, y: 48 },
|
||||
{ id: 'watchlists', label: 'Watchlists', sign: '視', x: 22, y: 65 },
|
||||
{ id: 'toolsntoys', label: 'ToolsnToys', sign: '⚙', x: 50, y: 72 },
|
||||
{ id: 'creatorlists', label: 'Creatorlists', sign: '創', x: 75, y: 70 }
|
||||
];
|
||||
|
||||
const starCanvas = document.getElementById('star-canvas');
|
||||
const nebulaCanvas = document.getElementById('nebula-canvas');
|
||||
const gridCanvas = document.getElementById('grid-canvas');
|
||||
const skyline = document.getElementById('skyline');
|
||||
const starZone = document.getElementById('star-zone');
|
||||
|
||||
// ── Parallax & Fading Logic ──
|
||||
function updateParallax() {
|
||||
const scrollY = window.scrollY || window.pageYOffset;
|
||||
const vh = window.innerHeight;
|
||||
const progress = Math.min(scrollY / vh, 1);
|
||||
|
||||
// 1. Receding Background (Slow Drift UP)
|
||||
const bgTranslate = -scrollY * 0.1;
|
||||
starCanvas.style.transform = `translateY(${bgTranslate}px)`;
|
||||
nebulaCanvas.style.transform = `translateY(${bgTranslate}px)`;
|
||||
gridCanvas.style.transform = `translateY(${bgTranslate}px)`;
|
||||
|
||||
// 2. Sequential Fading
|
||||
gridCanvas.style.opacity = Math.max(0, 1 - progress * 2.5); // Fades out by 40% scroll
|
||||
starCanvas.style.opacity = Math.max(0, 1 - progress * 1.2); // Fades out by 85% scroll
|
||||
nebulaCanvas.style.opacity = Math.max(0, 1 - progress * 1.5);
|
||||
|
||||
// 3. Skyline Ascent (Quickly Rising into Frame)
|
||||
const skyTranslate = -scrollY * 0.35;
|
||||
skyline.style.transform = `translateY(${skyTranslate}px)`;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', updateParallax, { passive: true });
|
||||
|
||||
// ── Starfield (Animated Drift) ──
|
||||
let bgStars = [];
|
||||
function initStars() {
|
||||
const w = window.innerWidth, h = window.innerHeight;
|
||||
starCanvas.width = w; starCanvas.height = h;
|
||||
bgStars = Array.from({length: 300}, () => ({
|
||||
x: Math.random() * w, y: Math.random() * h,
|
||||
r: Math.random() * 2,
|
||||
dx: (Math.random() - 0.5) * 0.06,
|
||||
dy: (Math.random() - 0.5) * 0.06,
|
||||
o: 0.15 + Math.random() * 0.5,
|
||||
phase: Math.random() * Math.PI * 2
|
||||
}));
|
||||
}
|
||||
|
||||
function drawStars(time) {
|
||||
const ctx = starCanvas.getContext('2d');
|
||||
ctx.clearRect(0,0,starCanvas.width, starCanvas.height);
|
||||
const t = time * 0.001;
|
||||
bgStars.forEach(s => {
|
||||
s.x += s.dx; s.y += s.dy;
|
||||
if (s.x < 0) s.x = starCanvas.width; if (s.x > starCanvas.width) s.x = 0;
|
||||
if (s.y < 0) s.y = starCanvas.height; if (s.y > starCanvas.height) s.y = 0;
|
||||
const alpha = s.o + Math.sin(t + s.phase) * 0.15;
|
||||
ctx.fillStyle = `rgba(232, 213, 184, ${alpha})`;
|
||||
ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, 6.28); ctx.fill();
|
||||
});
|
||||
requestAnimationFrame(drawStars);
|
||||
}
|
||||
|
||||
// ── Perspective Grid (Data Pulses) ──
|
||||
function drawGrid(time) {
|
||||
const ctx = gridCanvas.getContext('2d');
|
||||
const w = gridCanvas.width = gridCanvas.offsetWidth;
|
||||
const h = gridCanvas.height = gridCanvas.offsetHeight;
|
||||
ctx.clearRect(0,0,w,h);
|
||||
const pulsePos = (time * 0.05) % 100;
|
||||
|
||||
for(let i=0; i<18; i++) {
|
||||
let s = i/17;
|
||||
let y = h * (s*s);
|
||||
ctx.strokeStyle = `rgba(42, 196, 179, ${0.05 + s*0.2})`;
|
||||
if (Math.abs(s*100 - pulsePos) < 4) ctx.strokeStyle = `rgba(232, 148, 58, 0.4)`;
|
||||
ctx.lineWidth = 1.3;
|
||||
ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(w, y); ctx.stroke();
|
||||
}
|
||||
requestAnimationFrame(drawGrid);
|
||||
}
|
||||
|
||||
// ── Skyline (Massive Density) ──
|
||||
function buildSkyline() {
|
||||
const container = document.getElementById('skyline');
|
||||
container.innerHTML = '';
|
||||
const vw = window.innerWidth, vh = window.innerHeight;
|
||||
const count = 100;
|
||||
const clusterStart = Math.floor(count/2) - 4;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const b = document.createElement('div');
|
||||
b.className = 'building';
|
||||
b.style.width = (vw < 768 ? 40 : 80) + Math.random()*50 + 'px';
|
||||
b.style.height = (vh * 0.1 + Math.random() * (vh * 0.6)) + 'px';
|
||||
|
||||
if(Math.random() > 0.35) {
|
||||
const v = document.createElement('div');
|
||||
v.className = 'vine' + (Math.random() > 0.55 ? ' orchid' : '');
|
||||
v.style.left = '35%'; v.style.top = '12%';
|
||||
b.appendChild(v);
|
||||
}
|
||||
|
||||
// Brighter Windows
|
||||
if (Math.random() > 0.2 && b.style.height.replace('px','') > 60) {
|
||||
const win = document.createElement('span');
|
||||
win.style.cssText = `position:absolute;width:2px;height:2px;background:rgba(232,148,58,0.3);left:4px;top:10px;box-shadow:0 0 4px rgba(232,148,58,0.2);`;
|
||||
b.appendChild(win);
|
||||
}
|
||||
|
||||
if (i >= clusterStart && i < clusterStart + 8) {
|
||||
const star = STARS[i - clusterStart];
|
||||
const link = document.createElement('a');
|
||||
link.className = 'billboard-nav';
|
||||
link.textContent = star.sign;
|
||||
link.href = '#';
|
||||
link.onclick = (e) => { e.preventDefault(); selectStar(STARS.indexOf(star)); };
|
||||
b.appendChild(link);
|
||||
}
|
||||
container.appendChild(b);
|
||||
}
|
||||
}
|
||||
|
||||
function selectStar(idx) {
|
||||
const frame = document.getElementById('content-frame');
|
||||
frame.classList.remove('loaded');
|
||||
frame.srcdoc = `<html><body style="background:#0d1320;color:#e8d5b8;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;">
|
||||
<p>Opening ${STARS[idx].label}...</p></body></html>`;
|
||||
setTimeout(() => frame.classList.add('loaded'), 500);
|
||||
window.scrollTo({ top: document.getElementById('content-zone').offsetTop, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
document.getElementById('back-btn').onclick = () => window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
|
||||
// Init Star Nodes
|
||||
STARS.forEach((s, i) => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'star-node';
|
||||
btn.setAttribute('data-star', s.id);
|
||||
btn.style.left = s.x + '%'; btn.style.top = s.y + '%';
|
||||
btn.innerHTML = `<div class="star-visual"><span class="star-dot"></span></div><span class="star-label">${s.label}</span>`;
|
||||
btn.onclick = () => selectStar(i);
|
||||
starZone.appendChild(btn);
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => { initStars(); buildSkyline(); });
|
||||
initStars(); buildSkyline(); requestAnimationFrame(drawStars); requestAnimationFrame(drawGrid);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,554 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!--
|
||||
DRAFT: Starfield Bold v2
|
||||
AUTHOR: Gemini (Designer Agent)
|
||||
DATE: 2026-03-26
|
||||
|
||||
DESCRIPTION:
|
||||
A "BOLDER" fusion of vaporwave, Mad Max, and rainforest aesthetics.
|
||||
Nature has reclaimed the ruins, and the universe is pressing in.
|
||||
|
||||
NEW IN THIS VERSION:
|
||||
- EXPANDED STAR PALETTE: Orchid, Fairy Pink, Toucan Gold, Mint Green, Coral, Waterfall Teal.
|
||||
- BOLDER NEBULA WASHES: 5 layers (Orchid, Teal, Fairy Pink, Deep Purple, Amber) at 0.05 opacity.
|
||||
- CRT GHOST: Static scanlines (0.04 opacity) and phosphor vignette. NOT animated.
|
||||
- STAR BLOOM: Nodes grow from 8px to 18px on hover/focus via CSS width/height.
|
||||
- LUSH SKYLINE: Bioluminescent moss (mint/orchid) and polychromatic window lights.
|
||||
- BUMPED TEXT: 13px labels, 12px billboards, 16px lightbox body.
|
||||
- CAMPFIRE LIGHTBOX: Double-border with orchid inner frame and phosphor-green cursor line.
|
||||
|
||||
HARD CONSTRAINTS:
|
||||
- No transform animations on hover.
|
||||
- Border-radius: 10px max.
|
||||
- Box-shadow blur: 8px max.
|
||||
- Transitions: 150ms ease.
|
||||
- Font: Space Grotesk only.
|
||||
-->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Draft: Starfield Bold v2 - Gemini</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Space+Grotesk:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
/* Core Void */
|
||||
--bg-void: #04060b;
|
||||
--bg-deep: #060a14;
|
||||
--bg-warm: #0d1320;
|
||||
|
||||
/* The Campfire */
|
||||
--fire-amber: #e8943a;
|
||||
--fire-coral: #d4654a;
|
||||
--paradise: #ff7f3f;
|
||||
|
||||
/* Prismatic/Fairy Palette */
|
||||
--orchid: #c558d9;
|
||||
--fairy-pink: #f472b6;
|
||||
--toucan: #ffcf40;
|
||||
--mint-glow: #86efac;
|
||||
--neon-teal: #2ac4b3;
|
||||
--waterfall: #3fbfaf;
|
||||
--cosmic-purple:#4a1d6e;
|
||||
|
||||
/* CRT Ghost */
|
||||
--phosphor: #00ff41;
|
||||
|
||||
/* Text */
|
||||
--text-warm: #e8d5b8;
|
||||
--text-muted: #6a7a8a;
|
||||
|
||||
/* Constraints */
|
||||
--radius-std: 4px;
|
||||
--radius-max: 10px;
|
||||
--blur-std: 4px;
|
||||
--blur-max: 8px;
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg-void);
|
||||
color: var(--text-warm);
|
||||
overflow: hidden;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── CRT Ghost Layers ── */
|
||||
|
||||
/* Static Scanlines (texture only) */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
transparent,
|
||||
transparent 2px,
|
||||
rgba(0, 0, 0, 0.04) 2px,
|
||||
rgba(0, 0, 0, 0.04) 4px
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* Phosphor Vignette */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: radial-gradient(ellipse at center, transparent 60%, rgba(0, 0, 0, 0.35) 100%);
|
||||
pointer-events: none;
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
/* ── Zone 1: Star Map ── */
|
||||
|
||||
#star-zone {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(circle at 50% 50%, #0a0e1a 0%, var(--bg-void) 100%);
|
||||
}
|
||||
|
||||
#nebula-canvas, #star-canvas {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
|
||||
#nebula-canvas { z-index: 0; }
|
||||
#star-canvas { z-index: 1; }
|
||||
|
||||
#constellation-svg {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.constellation-line {
|
||||
stroke-width: 1.2;
|
||||
stroke-linecap: round;
|
||||
animation: line-pulse 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes line-pulse {
|
||||
0%, 100% { stroke-opacity: 0.1; }
|
||||
50% { stroke-opacity: 0.25; }
|
||||
}
|
||||
|
||||
/* ── Star Nodes ── */
|
||||
|
||||
.star-node {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
outline: none;
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.star-dot-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.star-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
transition: width 150ms ease, height 150ms ease, box-shadow 150ms ease, background 150ms ease;
|
||||
box-shadow: 0 0 var(--blur-std) #fff;
|
||||
}
|
||||
|
||||
.star-label {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: lowercase;
|
||||
white-space: nowrap;
|
||||
opacity: 0.6;
|
||||
transition: opacity 150ms ease, color 150ms ease;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Node Specificity */
|
||||
.star-node[data-star="writings"] .star-dot { background: var(--orchid); box-shadow: 0 0 6px var(--orchid); }
|
||||
.star-node[data-star="videos"] .star-dot { background: var(--fire-coral); box-shadow: 0 0 6px var(--fire-coral); }
|
||||
.star-node[data-star="music"] .star-dot { background: var(--neon-teal); box-shadow: 0 0 6px var(--neon-teal); }
|
||||
.star-node[data-star="images"] .star-dot { background: var(--mint-glow); box-shadow: 0 0 6px var(--mint-glow); }
|
||||
.star-node[data-star="playlists"] .star-dot { background: var(--fairy-pink); box-shadow: 0 0 6px var(--fairy-pink); }
|
||||
.star-node[data-star="watchlists"] .star-dot { background: var(--cosmic-purple); box-shadow: 0 0 6px var(--cosmic-purple); }
|
||||
.star-node[data-star="toolsntoys"] .star-dot { background: var(--toucan); box-shadow: 0 0 6px var(--toucan); }
|
||||
.star-node[data-star="creatorlists"] .star-dot { background: var(--waterfall); box-shadow: 0 0 6px var(--waterfall); }
|
||||
|
||||
/* Star Bloom (Hover/Focus) */
|
||||
.star-node:hover .star-dot,
|
||||
.star-node:focus .star-dot,
|
||||
.star-node.current .star-dot {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: var(--fire-amber) !important;
|
||||
box-shadow: 0 0 var(--blur-max) var(--fire-amber) !important;
|
||||
}
|
||||
|
||||
.star-node:hover .star-label,
|
||||
.star-node:focus .star-label,
|
||||
.star-node.current .star-label {
|
||||
color: var(--text-warm);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ── Transition Zone: Skyline ── */
|
||||
|
||||
#transition-zone {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 70vh;
|
||||
background: linear-gradient(to bottom, var(--bg-void) 0%, #080c14 40%, var(--bg-warm) 100%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#skyline {
|
||||
position: absolute;
|
||||
bottom: 0; left: 0;
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.building {
|
||||
background: #05080f;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(232, 148, 58, 0.05);
|
||||
}
|
||||
|
||||
/* Bioluminescent Moss & Highlights */
|
||||
.building.bio-orchid::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15%; left: 0;
|
||||
width: 2px; height: 35%;
|
||||
background: var(--orchid);
|
||||
box-shadow: 0 0 6px var(--orchid);
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.building.bio-mint::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 25%; right: 0;
|
||||
width: 1px; height: 30%;
|
||||
background: var(--mint-glow);
|
||||
box-shadow: 0 0 6px var(--mint-glow);
|
||||
opacity: 0.08;
|
||||
}
|
||||
|
||||
.billboard-nav {
|
||||
position: absolute;
|
||||
top: -2px; left: 50%;
|
||||
transform: translate(-50%, -100%);
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border: 1px solid;
|
||||
background: rgba(4, 6, 11, 0.95);
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
transition: color 150ms ease, border-color 150ms ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bb-teal { color: var(--neon-teal); border-color: rgba(42, 196, 179, 0.3); }
|
||||
.bb-amber { color: var(--fire-amber); border-color: rgba(232, 148, 58, 0.3); }
|
||||
.bb-orchid { color: var(--orchid); border-color: rgba(197, 88, 217, 0.3); }
|
||||
.bb-pink { color: var(--fairy-pink); border-color: rgba(244, 114, 182, 0.3); }
|
||||
.bb-mint { color: var(--mint-glow); border-color: rgba(134, 239, 172, 0.3); }
|
||||
|
||||
.billboard-nav:hover {
|
||||
color: var(--fire-amber) !important;
|
||||
border-color: var(--fire-amber) !important;
|
||||
}
|
||||
|
||||
/* ── Lightbox: Campfire Note ── */
|
||||
|
||||
#lightbox-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#lightbox-overlay.hidden { display: none; }
|
||||
|
||||
#lightbox {
|
||||
background: var(--bg-warm);
|
||||
border: 1px solid var(--fire-amber);
|
||||
border-top: 4px solid var(--phosphor); /* CRT Top Line */
|
||||
border-radius: var(--radius-std);
|
||||
padding: 40px;
|
||||
max-width: 520px;
|
||||
width: 90%;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Orchid Inner Border (Fairy Magic) */
|
||||
#lightbox::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 6px;
|
||||
border: 1px solid rgba(197, 88, 217, 0.12);
|
||||
pointer-events: none;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#lightbox p {
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
color: var(--text-warm);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.nav-hint {
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 32px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#lightbox-enter {
|
||||
padding: 10px 32px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--bg-void);
|
||||
background: var(--fire-amber);
|
||||
border: none;
|
||||
border-radius: var(--radius-std);
|
||||
cursor: pointer;
|
||||
transition: opacity 150ms ease;
|
||||
}
|
||||
|
||||
#lightbox-enter:hover { opacity: 0.9; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="star-zone">
|
||||
<canvas id="nebula-canvas"></canvas>
|
||||
<canvas id="star-canvas"></canvas>
|
||||
<svg id="constellation-svg" xmlns="http://www.w3.org/2000/svg"></svg>
|
||||
</div>
|
||||
|
||||
<div id="transition-zone">
|
||||
<div id="skyline"></div>
|
||||
</div>
|
||||
|
||||
<div id="lightbox-overlay" class="hidden">
|
||||
<div id="lightbox">
|
||||
<p>Hello traveller, welcome to a singular, particular space. Feel free to explore this little pocket of the universe. It's an adventure, bring snacks. Happy wanderings, Myster Wizzard</p>
|
||||
<span class="nav-hint">click stars · arrow keys · escape to return</span>
|
||||
<button id="lightbox-enter">Enter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STARS = [
|
||||
{ id: 'writings', label: 'Writings', x: 25, y: 18, color: '#c558d9' },
|
||||
{ id: 'videos', label: 'Videos', x: 68, y: 15, color: '#d4654a' },
|
||||
{ id: 'music', label: 'Music', x: 12, y: 42, color: '#2ac4b3' },
|
||||
{ id: 'images', label: 'Images', x: 55, y: 35, color: '#86efac' },
|
||||
{ id: 'playlists', label: 'Playlists', x: 78, y: 48, color: '#f472b6' },
|
||||
{ id: 'watchlists', label: 'Watchlists', x: 22, y: 65, color: '#4a1d6e' },
|
||||
{ id: 'toolsntoys', label: 'ToolsnToys', x: 50, y: 72, color: '#ffcf40' },
|
||||
{ id: 'creatorlists', label: 'Creatorlists', x: 75, y: 70, color: '#3fbfaf' }
|
||||
];
|
||||
|
||||
const nebulaCanvas = document.getElementById('nebula-canvas');
|
||||
const starCanvas = document.getElementById('star-canvas');
|
||||
const nCtx = nebulaCanvas.getContext('2d');
|
||||
const sCtx = starCanvas.getContext('2d');
|
||||
let bgStars = [];
|
||||
|
||||
function resize() {
|
||||
nebulaCanvas.width = starCanvas.width = window.innerWidth;
|
||||
nebulaCanvas.height = starCanvas.height = window.innerHeight;
|
||||
drawNebulae();
|
||||
initStars();
|
||||
}
|
||||
|
||||
function drawNebulae() {
|
||||
nCtx.clearRect(0, 0, nebulaCanvas.width, nebulaCanvas.height);
|
||||
const washes = [
|
||||
{ x: 0.2, y: 0.3, r: 0.5, color: 'rgba(197, 88, 217, 0.05)' }, // Orchid
|
||||
{ x: 0.8, y: 0.2, r: 0.6, color: 'rgba(42, 196, 179, 0.05)' }, // Teal
|
||||
{ x: 0.5, y: 0.7, r: 0.5, color: 'rgba(244, 114, 182, 0.05)' }, // Fairy Pink
|
||||
{ x: 0.7, y: 0.8, r: 0.4, color: 'rgba(74, 29, 110, 0.06)' }, // Deep Purple
|
||||
{ x: 0.3, y: 0.6, r: 0.5, color: 'rgba(232, 148, 58, 0.04)' } // Amber
|
||||
];
|
||||
|
||||
washes.forEach(w => {
|
||||
const grad = nCtx.createRadialGradient(
|
||||
w.x * nebulaCanvas.width, w.y * nebulaCanvas.height, 0,
|
||||
w.x * nebulaCanvas.width, w.y * nebulaCanvas.height, w.r * nebulaCanvas.width
|
||||
);
|
||||
grad.addColorStop(0, w.color);
|
||||
grad.addColorStop(1, 'transparent');
|
||||
nCtx.fillStyle = grad;
|
||||
nCtx.fillRect(0, 0, nebulaCanvas.width, nebulaCanvas.height);
|
||||
});
|
||||
}
|
||||
|
||||
function initStars() {
|
||||
bgStars = [];
|
||||
const colorClasses = [
|
||||
'rgba(200,210,230,', // Cool White
|
||||
'rgba(240,220,190,', // Warm White
|
||||
'rgba(140,180,230,', // Pale Blue
|
||||
'rgba(255,207,64,', // Toucan Gold
|
||||
'rgba(244,114,182,', // Fairy Pink
|
||||
'rgba(197,88,217,', // Orchid Purple
|
||||
'rgba(134,239,172,', // Mint Green
|
||||
'rgba(212,101,74,' // Coral
|
||||
];
|
||||
|
||||
for(let i=0; i<350; i++) {
|
||||
const r = Math.random() < 0.1 ? Math.random() * 1.5 + 1.5 : Math.random() * 1.5 + 0.3;
|
||||
bgStars.push({
|
||||
x: Math.random() * starCanvas.width,
|
||||
y: Math.random() * starCanvas.height,
|
||||
r: r,
|
||||
colorBase: colorClasses[Math.floor(Math.random()*colorClasses.length)],
|
||||
opacity: Math.random() * 0.7 + 0.3,
|
||||
speed: Math.random() * 0.8 + 0.2,
|
||||
phase: Math.random() * Math.PI * 2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function draw(time) {
|
||||
sCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);
|
||||
const t = time * 0.001;
|
||||
bgStars.forEach(s => {
|
||||
const a = s.opacity + Math.sin(t * s.speed + s.phase) * 0.2;
|
||||
sCtx.beginPath();
|
||||
sCtx.arc(s.x, s.y, s.r, 0, Math.PI*2);
|
||||
sCtx.fillStyle = s.colorBase + Math.max(0.1, Math.min(1, a)) + ')';
|
||||
sCtx.fill();
|
||||
});
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
// Nodes & Lines
|
||||
const starZone = document.getElementById('star-zone');
|
||||
const svg = document.getElementById('constellation-svg');
|
||||
|
||||
STARS.forEach(s => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'star-node';
|
||||
btn.dataset.star = s.id;
|
||||
btn.style.left = s.x + '%';
|
||||
btn.style.top = s.y + '%';
|
||||
btn.innerHTML = `<div class="star-dot-container"><span class="star-dot"></span></div><span class="star-label">${s.label}</span>`;
|
||||
starZone.appendChild(btn);
|
||||
});
|
||||
|
||||
const lines = [['writings','videos'],['music','playlists'],['images','videos'],['watchlists','toolsntoys'],['toolsntoys','creatorlists'],['music','watchlists']];
|
||||
lines.forEach(pair => {
|
||||
const s1 = STARS.find(s => s.id === pair[0]);
|
||||
const s2 = STARS.find(s => s.id === pair[1]);
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', s1.x + '%'); line.setAttribute('y1', s1.y + '%');
|
||||
line.setAttribute('x2', s2.x + '%'); line.setAttribute('y2', s2.y + '%');
|
||||
line.setAttribute('class', 'constellation-line');
|
||||
line.setAttribute('stroke', s1.color);
|
||||
line.setAttribute('stroke-opacity', '0.15');
|
||||
svg.appendChild(line);
|
||||
});
|
||||
|
||||
// Skyline
|
||||
function initSkyline() {
|
||||
const skyline = document.getElementById('skyline');
|
||||
const bbColors = ['bb-teal', 'bb-amber', 'bb-orchid', 'bb-pink', 'bb-mint'];
|
||||
const winColors = ['var(--fire-amber)', 'var(--neon-teal)', 'var(--orchid)', 'var(--fairy-pink)', 'var(--phosphor)'];
|
||||
|
||||
for(let i=0; i<40; i++) {
|
||||
const b = document.createElement('div');
|
||||
b.className = 'building';
|
||||
const bio = Math.random();
|
||||
if(bio > 0.85) b.classList.add('bio-orchid');
|
||||
else if(bio > 0.75) b.classList.add('bio-mint');
|
||||
|
||||
const w = 20 + Math.random() * 60;
|
||||
const h = 40 + Math.random() * 300;
|
||||
b.style.width = w + 'px';
|
||||
b.style.height = h + 'px';
|
||||
b.style.marginRight = '2px';
|
||||
|
||||
if(h > 80) {
|
||||
for(let j=0; j<Math.floor(h/30); j++) {
|
||||
const win = document.createElement('div');
|
||||
const wc = winColors[Math.floor(Math.random()*winColors.length)];
|
||||
win.style.cssText = `position:absolute; width:2px; height:2px; background:${wc}; opacity:${Math.random()*0.3}; left:${Math.random()*w}px; top:${30+j*30}px;`;
|
||||
b.appendChild(win);
|
||||
}
|
||||
}
|
||||
|
||||
if(Math.random() > 0.85) {
|
||||
const bb = document.createElement('div');
|
||||
bb.className = 'billboard-nav ' + bbColors[Math.floor(Math.random()*bbColors.length)];
|
||||
bb.textContent = 'SIGNAL';
|
||||
b.appendChild(bb);
|
||||
}
|
||||
skyline.appendChild(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Lightbox
|
||||
const overlay = document.getElementById('lightbox-overlay');
|
||||
if(!localStorage.getItem('sp-welcomed')) overlay.classList.remove('hidden');
|
||||
document.getElementById('lightbox-enter').onclick = () => {
|
||||
overlay.classList.add('hidden');
|
||||
localStorage.setItem('sp-welcomed', 'true');
|
||||
};
|
||||
|
||||
window.onresize = resize;
|
||||
resize();
|
||||
initSkyline();
|
||||
requestAnimationFrame(draw);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,596 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!--
|
||||
DRAFT: Starfield Bold v3 (The Prismatic Ruins)
|
||||
AUTHOR: Gemini (Designer Agent)
|
||||
DATE: 2026-03-26
|
||||
|
||||
DESCRIPTION:
|
||||
The "BOLDER" direction v2: Vaporwave + Mad Max + Rainforest + Fairies.
|
||||
Focus on "Visible Personality" for stars and a deeper "Enchanted Twilight" feel.
|
||||
|
||||
NEW IN THIS VERSION:
|
||||
- STAR NODE PERSONALITIES: Each node is a unique celestial/magical object (Beacon, Binary, Pulsar, Flora, Hearth, Nebula Point, Spark, Flow).
|
||||
- REFINED CRT GHOST: Precision scanlines (0.04) and phosphor vignette. 1px phosphor line on Lightbox.
|
||||
- ENHANCED STAR FIELD: Weighted 8-color distribution (Cool/Warm White, Blue, Gold, Pink, Orchid, Mint, Coral).
|
||||
- PRISMATIC NEBULAE: 5 layers with slightly higher saturation but low opacity (0.05).
|
||||
- LUSH SKYLINE: Polychromatic window lights (Amber/Teal/Orchid/Pink/Phosphor) and Mint/Orchid bioluminescence.
|
||||
- BUMPED TEXT: 13px star labels, 12px billboards, 16px lightbox body.
|
||||
- CAMPFIRE LIGHTBOX: Double-border with orchid-fairy magic and phosphor cursor line.
|
||||
|
||||
CONSTRAINTS:
|
||||
- No transform animations on hover (using width/height).
|
||||
- Transitions 150ms ease.
|
||||
- Border-radius max 10px.
|
||||
- Box-shadow blur max 8px.
|
||||
- Font: Space Grotesk.
|
||||
-->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Singular Particular Space | Starfield Bold v3</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Space+Grotesk:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
/* Core Void */
|
||||
--bg-void: #04060b;
|
||||
--bg-deep: #060a14;
|
||||
--bg-warm: #0d1320;
|
||||
|
||||
/* The Campfire */
|
||||
--fire-amber: #e8943a;
|
||||
--fire-coral: #d4654a;
|
||||
--paradise: #ff7f3f;
|
||||
|
||||
/* Prismatic/Fairy Palette */
|
||||
--orchid: #c558d9;
|
||||
--fairy-pink: #f472b6;
|
||||
--toucan-gold: #ffcf40;
|
||||
--mint-glow: #86efac;
|
||||
--neon-teal: #2ac4b3;
|
||||
--waterfall: #3fbfaf;
|
||||
--cosmic-purple:#4a1d6e;
|
||||
|
||||
/* CRT Ghost */
|
||||
--phosphor: #00ff41;
|
||||
|
||||
/* Text */
|
||||
--text-warm: #e8d5b8;
|
||||
--text-muted: #6a7a8a;
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg-void);
|
||||
color: var(--text-warm);
|
||||
overflow: hidden;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── CRT GHOST LAYERS ── */
|
||||
|
||||
/* Static Scanlines */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
transparent,
|
||||
transparent 2px,
|
||||
rgba(0, 0, 0, 0.04) 2px,
|
||||
rgba(0, 0, 0, 0.04) 4px
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* Phosphor Vignette */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: radial-gradient(ellipse at center, transparent 60%, rgba(0, 0, 0, 0.35) 100%);
|
||||
pointer-events: none;
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
/* ── Zone 1: Star Map ── */
|
||||
|
||||
#star-zone {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(circle at 50% 50%, #0a0e1a 0%, var(--bg-void) 100%);
|
||||
}
|
||||
|
||||
#nebula-canvas, #star-canvas {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
|
||||
#nebula-canvas { z-index: 0; }
|
||||
#star-canvas { z-index: 1; }
|
||||
|
||||
#constellation-svg {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.constellation-line {
|
||||
stroke-width: 1.2;
|
||||
stroke-linecap: round;
|
||||
animation: line-pulse 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes line-pulse {
|
||||
0%, 100% { stroke-opacity: 0.08; }
|
||||
50% { stroke-opacity: 0.25; }
|
||||
}
|
||||
|
||||
/* ── Star Nodes (Personality Layer) ── */
|
||||
|
||||
.star-node {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
outline: none;
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.star-visual {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.star-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
transition: width 150ms ease, height 150ms ease, box-shadow 150ms ease, background 150ms ease;
|
||||
box-shadow: 0 0 4px #fff;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.star-label {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: lowercase;
|
||||
white-space: nowrap;
|
||||
opacity: 0.6;
|
||||
transition: opacity 150ms ease, color 150ms ease;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Star Bloom (Hover/Focus) */
|
||||
.star-node:hover .star-dot,
|
||||
.star-node:focus .star-dot,
|
||||
.star-node.current .star-dot {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: var(--fire-amber) !important;
|
||||
box-shadow: 0 0 8px var(--fire-amber) !important;
|
||||
}
|
||||
|
||||
.star-node:hover .star-label,
|
||||
.star-node:focus .star-label,
|
||||
.star-node.current .star-label {
|
||||
color: var(--text-warm);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Personality 1: Writings (The Beacon) - Cross-hair glow */
|
||||
.star-node[data-star="writings"] .star-dot { background: var(--orchid); box-shadow: 0 0 6px var(--orchid); }
|
||||
.star-node[data-star="writings"] .star-visual::before,
|
||||
.star-node[data-star="writings"] .star-visual::after {
|
||||
content: ''; position: absolute; background: var(--orchid); opacity: 0.2; transition: opacity 150ms;
|
||||
}
|
||||
.star-node[data-star="writings"] .star-visual::before { width: 1px; height: 100%; }
|
||||
.star-node[data-star="writings"] .star-visual::after { width: 100%; height: 1px; }
|
||||
|
||||
/* Personality 2: Videos (The Binary) - Twin dots */
|
||||
.star-node[data-star="videos"] .star-dot { background: var(--fire-coral); box-shadow: 0 0 6px var(--fire-coral); }
|
||||
.star-node[data-star="videos"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 4px; height: 4px; border-radius: 50%;
|
||||
background: var(--fire-coral); top: 0; right: 0; opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Personality 3: Music (The Pulsar) - Multiple small dots */
|
||||
.star-node[data-star="music"] .star-dot { background: var(--neon-teal); box-shadow: 0 0 6px var(--neon-teal); }
|
||||
.star-node[data-star="music"] .star-visual::before {
|
||||
content: '· ·'; position: absolute; color: var(--neon-teal); font-size: 16px; top: -10px; opacity: 0.4;
|
||||
}
|
||||
|
||||
/* Personality 4: Images (The Flora) - Soft halo */
|
||||
.star-node[data-star="images"] .star-dot { background: var(--mint-glow); box-shadow: 0 0 6px var(--mint-glow); }
|
||||
.star-node[data-star="images"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 20px; height: 20px; border-radius: 50%;
|
||||
border: 1px solid var(--mint-glow); opacity: 0.15;
|
||||
}
|
||||
|
||||
/* Personality 5: Playlists (The Hearth) - Intense flicker */
|
||||
.star-node[data-star="playlists"] .star-dot {
|
||||
background: var(--fairy-pink); box-shadow: 0 0 6px var(--fairy-pink);
|
||||
animation: hearth-flicker 4s ease-in-out infinite;
|
||||
}
|
||||
@keyframes hearth-flicker { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }
|
||||
|
||||
/* Personality 6: Watchlists (The Nebula Point) - Tiny cloud */
|
||||
.star-node[data-star="watchlists"] .star-dot { background: var(--cosmic-purple); box-shadow: 0 0 6px var(--cosmic-purple); }
|
||||
.star-node[data-star="watchlists"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 24px; height: 24px; border-radius: 50%;
|
||||
background: radial-gradient(circle, var(--cosmic-purple) 0%, transparent 70%); opacity: 0.2;
|
||||
}
|
||||
|
||||
/* Personality 7: Tools (The Spark) - Sharp intense */
|
||||
.star-node[data-star="toolsntoys"] .star-dot { background: var(--toucan-gold); box-shadow: 0 0 8px var(--toucan-gold); width: 6px; height: 6px; }
|
||||
|
||||
/* Personality 8: Creatorlists (The Flow) - Trail */
|
||||
.star-node[data-star="creatorlists"] .star-dot { background: var(--waterfall); box-shadow: 0 0 6px var(--waterfall); }
|
||||
.star-node[data-star="creatorlists"] .star-visual::before {
|
||||
content: '...'; position: absolute; color: var(--waterfall); right: -12px; font-size: 10px; opacity: 0.3;
|
||||
}
|
||||
|
||||
/* ── Transition Zone: Skyline ── */
|
||||
|
||||
#transition-zone {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 80vh;
|
||||
background: linear-gradient(to bottom, var(--bg-void) 0%, #080c14 40%, var(--bg-warm) 100%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#skyline {
|
||||
position: absolute;
|
||||
bottom: 0; left: 0;
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.building {
|
||||
background: #05080f;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(232, 148, 58, 0.04);
|
||||
}
|
||||
|
||||
/* Bioluminescent Moss & Highlights */
|
||||
.building.bio-orchid::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15%; left: 0;
|
||||
width: 2px; height: 40%;
|
||||
background: var(--orchid);
|
||||
box-shadow: 0 0 6px var(--orchid);
|
||||
opacity: 0.12;
|
||||
}
|
||||
|
||||
.building.bio-mint::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 25%; right: 0;
|
||||
width: 1px; height: 35%;
|
||||
background: var(--mint-glow);
|
||||
box-shadow: 0 0 6px var(--mint-glow);
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.billboard-nav {
|
||||
position: absolute;
|
||||
top: -2px; left: 50%;
|
||||
transform: translate(-50%, -100%);
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border: 1px solid;
|
||||
background: rgba(4, 6, 11, 0.95);
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
transition: color 150ms ease, border-color 150ms ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bb-teal { color: var(--neon-teal); border-color: rgba(42, 196, 179, 0.2); }
|
||||
.bb-amber { color: var(--fire-amber); border-color: rgba(232, 148, 58, 0.2); }
|
||||
.bb-orchid { color: var(--orchid); border-color: rgba(197, 88, 217, 0.2); }
|
||||
.bb-pink { color: var(--fairy-pink); border-color: rgba(244, 114, 182, 0.2); }
|
||||
.bb-mint { color: var(--mint-glow); border-color: rgba(134, 239, 172, 0.2); }
|
||||
|
||||
.billboard-nav:hover {
|
||||
color: var(--fire-amber) !important;
|
||||
border-color: var(--fire-amber) !important;
|
||||
}
|
||||
|
||||
/* ── Lightbox: Campfire Note ── */
|
||||
|
||||
#lightbox-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#lightbox-overlay.hidden { display: none; }
|
||||
|
||||
#lightbox {
|
||||
background: var(--bg-warm);
|
||||
border: 1px solid var(--fire-amber);
|
||||
border-top: 4px solid var(--phosphor); /* CRT Cursor Line */
|
||||
border-radius: 4px;
|
||||
padding: 40px;
|
||||
max-width: 520px;
|
||||
width: 90%;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Orchid Inner Border (Fairy Magic) */
|
||||
#lightbox::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 6px;
|
||||
border: 1px solid rgba(197, 88, 217, 0.15);
|
||||
pointer-events: none;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#lightbox p {
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
color: var(--text-warm);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.nav-hint {
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 32px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#lightbox-enter {
|
||||
padding: 10px 32px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--bg-void);
|
||||
background: var(--fire-amber);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: opacity 150ms ease;
|
||||
}
|
||||
|
||||
#lightbox-enter:hover { opacity: 0.9; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="star-zone">
|
||||
<canvas id="nebula-canvas"></canvas>
|
||||
<canvas id="star-canvas"></canvas>
|
||||
<svg id="constellation-svg" xmlns="http://www.w3.org/2000/svg"></svg>
|
||||
</div>
|
||||
|
||||
<div id="transition-zone">
|
||||
<div id="skyline"></div>
|
||||
</div>
|
||||
|
||||
<div id="lightbox-overlay" class="hidden">
|
||||
<div id="lightbox">
|
||||
<p>Hello traveller, welcome to a singular, particular space. Feel free to explore this little pocket of the universe. It's an adventure, bring snacks. Happy wanderings, Myster Wizzard</p>
|
||||
<span class="nav-hint">click stars · arrow keys · escape to return</span>
|
||||
<button id="lightbox-enter">Enter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STARS = [
|
||||
{ id: 'writings', label: 'Writings', x: 25, y: 18, color: '#c558d9' },
|
||||
{ id: 'videos', label: 'Videos', x: 68, y: 15, color: '#d4654a' },
|
||||
{ id: 'music', label: 'Music', x: 12, y: 42, color: '#2ac4b3' },
|
||||
{ id: 'images', label: 'Images', x: 55, y: 35, color: '#86efac' },
|
||||
{ id: 'playlists', label: 'Playlists', x: 78, y: 48, color: '#f472b6' },
|
||||
{ id: 'watchlists', label: 'Watchlists', x: 22, y: 65, color: '#4a1d6e' },
|
||||
{ id: 'toolsntoys', label: 'ToolsnToys', x: 50, y: 72, color: '#ffcf40' },
|
||||
{ id: 'creatorlists', label: 'Creatorlists', x: 75, y: 70, color: '#3fbfaf' }
|
||||
];
|
||||
|
||||
const CONNECTIONS = [
|
||||
['writings', 'videos'], ['music', 'playlists'], ['images', 'videos'],
|
||||
['watchlists', 'toolsntoys'], ['toolsntoys', 'creatorlists'], ['music', 'watchlists']
|
||||
];
|
||||
|
||||
const nebulaCanvas = document.getElementById('nebula-canvas');
|
||||
const starCanvas = document.getElementById('star-canvas');
|
||||
const nCtx = nebulaCanvas.getContext('2d');
|
||||
const sCtx = starCanvas.getContext('2d');
|
||||
let bgStars = [];
|
||||
|
||||
function resize() {
|
||||
nebulaCanvas.width = starCanvas.width = window.innerWidth;
|
||||
nebulaCanvas.height = starCanvas.height = window.innerHeight;
|
||||
drawNebulae();
|
||||
initStars();
|
||||
}
|
||||
|
||||
function drawNebulae() {
|
||||
nCtx.clearRect(0, 0, nebulaCanvas.width, nebulaCanvas.height);
|
||||
const washes = [
|
||||
{ x: 0.2, y: 0.3, r: 0.5, color: 'rgba(197, 88, 217, 0.05)' }, // Orchid
|
||||
{ x: 0.8, y: 0.2, r: 0.6, color: 'rgba(42, 196, 179, 0.05)' }, // Teal
|
||||
{ x: 0.5, y: 0.7, r: 0.5, color: 'rgba(244, 114, 182, 0.05)' }, // Fairy Pink
|
||||
{ x: 0.7, y: 0.8, r: 0.4, color: 'rgba(74, 29, 110, 0.06)' }, // Deep Purple
|
||||
{ x: 0.3, y: 0.6, r: 0.5, color: 'rgba(232, 148, 58, 0.04)' } // Amber
|
||||
];
|
||||
|
||||
washes.forEach(w => {
|
||||
const grad = nCtx.createRadialGradient(
|
||||
w.x * nebulaCanvas.width, w.y * nebulaCanvas.height, 0,
|
||||
w.x * nebulaCanvas.width, w.y * nebulaCanvas.height, w.r * nebulaCanvas.width
|
||||
);
|
||||
grad.addColorStop(0, w.color);
|
||||
grad.addColorStop(1, 'transparent');
|
||||
nCtx.fillStyle = grad;
|
||||
nCtx.fillRect(0, 0, nebulaCanvas.width, nebulaCanvas.height);
|
||||
});
|
||||
}
|
||||
|
||||
function initStars() {
|
||||
bgStars = [];
|
||||
const colorClasses = [
|
||||
'rgba(200,210,230,', // Cool White
|
||||
'rgba(240,220,190,', // Warm White
|
||||
'rgba(140,180,230,', // Pale Blue
|
||||
'rgba(255,207,64,', // Toucan Gold
|
||||
'rgba(244,114,182,', // Fairy Pink
|
||||
'rgba(197,88,217,', // Orchid
|
||||
'rgba(134,239,172,', // Mint Green
|
||||
'rgba(212,101,74,' // Coral
|
||||
];
|
||||
|
||||
for(let i=0; i<350; i++) {
|
||||
const r = Math.random() < 0.1 ? Math.random() * 1.5 + 1.5 : Math.random() * 1.5 + 0.3;
|
||||
bgStars.push({
|
||||
x: Math.random() * starCanvas.width,
|
||||
y: Math.random() * starCanvas.height,
|
||||
r: r,
|
||||
colorBase: colorClasses[Math.floor(Math.random()*colorClasses.length)],
|
||||
opacity: Math.random() * 0.7 + 0.3,
|
||||
speed: Math.random() * 0.6 + 0.2,
|
||||
phase: Math.random() * Math.PI * 2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function draw(time) {
|
||||
sCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);
|
||||
const t = time * 0.001;
|
||||
bgStars.forEach(s => {
|
||||
const a = s.opacity + Math.sin(t * s.speed + s.phase) * 0.2;
|
||||
sCtx.beginPath();
|
||||
sCtx.arc(s.x, s.y, s.r, 0, Math.PI*2);
|
||||
sCtx.fillStyle = s.colorBase + Math.max(0.1, Math.min(1, a)) + ')';
|
||||
sCtx.fill();
|
||||
});
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
// Nodes & Lines
|
||||
const starZone = document.getElementById('star-zone');
|
||||
const svg = document.getElementById('constellation-svg');
|
||||
|
||||
STARS.forEach(s => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'star-node';
|
||||
btn.dataset.star = s.id;
|
||||
btn.style.left = s.x + '%';
|
||||
btn.style.top = s.y + '%';
|
||||
btn.innerHTML = `<div class="star-visual"><span class="star-dot"></span></div><span class="star-label">${s.label}</span>`;
|
||||
starZone.appendChild(btn);
|
||||
});
|
||||
|
||||
CONNECTIONS.forEach(pair => {
|
||||
const s1 = STARS.find(s => s.id === pair[0]);
|
||||
const s2 = STARS.find(s => s.id === pair[1]);
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', s1.x + '%'); line.setAttribute('y1', s1.y + '%');
|
||||
line.setAttribute('x2', s2.x + '%'); line.setAttribute('y2', s2.y + '%');
|
||||
line.setAttribute('class', 'constellation-line');
|
||||
line.setAttribute('stroke', s1.color);
|
||||
line.setAttribute('stroke-opacity', '0.15');
|
||||
svg.appendChild(line);
|
||||
});
|
||||
|
||||
// Skyline
|
||||
function initSkyline() {
|
||||
const skyline = document.getElementById('skyline');
|
||||
const bbColors = ['bb-teal', 'bb-amber', 'bb-orchid', 'bb-pink', 'bb-mint'];
|
||||
const winColors = ['var(--fire-amber)', 'var(--neon-teal)', 'var(--orchid)', 'var(--fairy-pink)', 'var(--phosphor)'];
|
||||
|
||||
for(let i=0; i<45; i++) {
|
||||
const b = document.createElement('div');
|
||||
b.className = 'building';
|
||||
const bio = Math.random();
|
||||
if(bio > 0.88) b.classList.add('bio-orchid');
|
||||
else if(bio > 0.75) b.classList.add('bio-mint');
|
||||
|
||||
const w = 18 + Math.random() * 55;
|
||||
const h = 40 + Math.random() * 320;
|
||||
b.style.width = w + 'px';
|
||||
b.style.height = h + 'px';
|
||||
b.style.marginRight = '2px';
|
||||
|
||||
if(h > 80) {
|
||||
for(let j=0; j<Math.floor(h/35); j++) {
|
||||
const win = document.createElement('div');
|
||||
const wc = winColors[Math.floor(Math.random()*winColors.length)];
|
||||
win.style.cssText = `position:absolute; width:2px; height:2px; background:${wc}; opacity:${Math.random()*0.3}; left:${Math.random()*w}px; top:${30+j*30}px;`;
|
||||
b.appendChild(win);
|
||||
}
|
||||
}
|
||||
|
||||
if(Math.random() > 0.88) {
|
||||
const bb = document.createElement('div');
|
||||
bb.className = 'billboard-nav ' + bbColors[Math.floor(Math.random()*bbColors.length)];
|
||||
bb.textContent = 'SIGNAL';
|
||||
b.appendChild(bb);
|
||||
}
|
||||
skyline.appendChild(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Lightbox
|
||||
const overlay = document.getElementById('lightbox-overlay');
|
||||
if(!localStorage.getItem('sp-welcomed')) overlay.classList.remove('hidden');
|
||||
document.getElementById('lightbox-enter').onclick = () => {
|
||||
overlay.classList.add('hidden');
|
||||
localStorage.setItem('sp-welcomed', 'true');
|
||||
};
|
||||
|
||||
window.onresize = resize;
|
||||
resize();
|
||||
initSkyline();
|
||||
requestAnimationFrame(draw);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,528 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!--
|
||||
DRAFT: Starfield Celestial v4 (The Infinite Night Market)
|
||||
AUTHOR: Gemini (Designer Agent)
|
||||
DATE: 2026-03-26
|
||||
|
||||
DESCRIPTION:
|
||||
The "CELESTIAL" pivot: Constellation lines REMOVED per user request.
|
||||
Focus shifts to "Visible Personality" of nodes and a more atmospheric,
|
||||
dense star field that feels like a place rather than a UI.
|
||||
|
||||
NEW IN THIS VERSION:
|
||||
- NO CONSTELLATION LINES: The connections are now felt, not seen.
|
||||
- STAR NODE PERSONALITIES v2:
|
||||
- Writings (Beacon): Pulsing cross-hair glow.
|
||||
- Videos (Binary): Orbiting secondary spark.
|
||||
- Music (Pulsar): Rapid-flicker rhythmic aura.
|
||||
- Images (Flora): Concentric mint-glow rings (Bioluminescent Moss).
|
||||
- Playlists (Hearth): Warm amber flame flicker.
|
||||
- Watchlists (Nebula Point): Soft purple gas cloud halo.
|
||||
- ToolsnToys (Spark): Sharp, prismatic star-spike.
|
||||
- Creatorlists (Flow): Trailing mint-green comet dust.
|
||||
- BOLDER NEBULAE: 6 overlapping washes (Orchid, Paradise, Toucan, Teal, Pink, Purple).
|
||||
- VAST CELESTIAL FIELD: 3 depth layers, 8-color distribution, rare "Mega Stars" (3px).
|
||||
- LUSH RUINS SKYLINE: Vertical bioluminescent stripes (Orchid/Mint) on silhouettes.
|
||||
- TEXT BUMP: 16px star labels (desktop), 13px billboard nav.
|
||||
|
||||
AESTHETIC: Vaporwave Ruins + Mad Max Rainforest + Fairy Fire.
|
||||
-->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Singular Particular Space | Starfield Celestial v4</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Space+Grotesk:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
/* The Void */
|
||||
--bg-void: #04060b;
|
||||
--bg-deep: #060a14;
|
||||
--bg-warm: #0d1320;
|
||||
|
||||
/* The Fire */
|
||||
--fire-amber: #e8943a;
|
||||
--fire-coral: #d4654a;
|
||||
--paradise: #ff7f3f;
|
||||
|
||||
/* The Magic */
|
||||
--orchid: #c558d9;
|
||||
--fairy-pink: #f472b6;
|
||||
--toucan-gold: #ffcf40;
|
||||
--mint-glow: #86efac;
|
||||
--neon-teal: #2ac4b3;
|
||||
--waterfall: #3fbfaf;
|
||||
--cosmic-purple: #4a1d6e;
|
||||
|
||||
/* The Tech Ghost */
|
||||
--phosphor: #00ff41;
|
||||
|
||||
/* The Human */
|
||||
--text-warm: #e8d5b8;
|
||||
--text-muted: #6a7a8a;
|
||||
}
|
||||
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg-void);
|
||||
color: var(--text-warm);
|
||||
overflow: hidden;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── CRT Ghost ── */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
transparent,
|
||||
transparent 2px,
|
||||
rgba(0, 0, 0, 0.04) 2px,
|
||||
rgba(0, 0, 0, 0.04) 4px
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* ── Zone 1: Star Map ── */
|
||||
|
||||
#star-zone {
|
||||
position: relative;
|
||||
width: 100%; height: 100vh;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(circle at 50% 50%, #080c18 0%, var(--bg-void) 100%);
|
||||
}
|
||||
|
||||
#nebula-canvas, #star-canvas {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
|
||||
#nebula-canvas { z-index: 0; }
|
||||
#star-canvas { z-index: 1; }
|
||||
|
||||
/* ── Star Nodes (Personality Layer) ── */
|
||||
|
||||
.star-node {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
outline: none;
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.star-visual {
|
||||
position: relative;
|
||||
width: 40px; height: 40px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
|
||||
.star-dot {
|
||||
width: 8px; height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
transition: width 150ms ease, height 150ms ease, box-shadow 150ms ease, background 150ms ease;
|
||||
box-shadow: 0 0 6px rgba(255,255,255,0.8);
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.star-label {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: lowercase;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
transition: opacity 200ms ease, color 150ms ease;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.star-node:hover .star-label,
|
||||
.star-node:focus .star-label,
|
||||
.star-node.current .star-label { opacity: 1; color: var(--text-warm); }
|
||||
|
||||
/* Star Bloom (The Campfire Follows You) */
|
||||
.star-node:hover .star-dot,
|
||||
.star-node:focus .star-dot,
|
||||
.star-node.current .star-dot {
|
||||
width: 20px; height: 20px;
|
||||
background: var(--fire-amber) !important;
|
||||
box-shadow: 0 0 12px var(--fire-amber) !important;
|
||||
}
|
||||
|
||||
/* Personality 1: Writings (The Beacon) */
|
||||
.star-node[data-star="writings"] .star-dot { background: var(--star-blue, #a0c4ff); box-shadow: 0 0 8px #a0c4ff; }
|
||||
.star-node[data-star="writings"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 1px; height: 100%; background: var(--orchid); opacity: 0.15;
|
||||
animation: beacon-pulse 4s ease-in-out infinite;
|
||||
}
|
||||
.star-node[data-star="writings"] .star-visual::after {
|
||||
content: ''; position: absolute; width: 100%; height: 1px; background: var(--orchid); opacity: 0.15;
|
||||
animation: beacon-pulse 4s ease-in-out infinite;
|
||||
}
|
||||
@keyframes beacon-pulse { 0%, 100% { opacity: 0.05; } 50% { opacity: 0.25; } }
|
||||
|
||||
/* Personality 2: Videos (The Binary) */
|
||||
.star-node[data-star="videos"] .star-dot { background: var(--fire-coral); box-shadow: 0 0 8px var(--fire-coral); }
|
||||
.star-node[data-star="videos"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 4px; height: 4px; border-radius: 50%;
|
||||
background: #fff; opacity: 0.6;
|
||||
animation: binary-orbit 3s linear infinite;
|
||||
}
|
||||
@keyframes binary-orbit {
|
||||
from { transform: rotate(0deg) translateX(12px) rotate(0deg); }
|
||||
to { transform: rotate(360deg) translateX(12px) rotate(-360deg); }
|
||||
}
|
||||
|
||||
/* Personality 3: Music (The Pulsar) */
|
||||
.star-node[data-star="music"] .star-dot { background: var(--neon-teal); box-shadow: 0 0 8px var(--neon-teal); }
|
||||
.star-node[data-star="music"] .star-visual::before {
|
||||
content: ''; position: absolute; inset: 0; border: 1px solid var(--neon-teal); border-radius: 50%;
|
||||
animation: pulsar-aura 2s ease-out infinite;
|
||||
}
|
||||
@keyframes pulsar-aura { 0% { transform: scale(0.2); opacity: 0.6; } 100% { transform: scale(1.2); opacity: 0; } }
|
||||
|
||||
/* Personality 4: Images (The Flora) */
|
||||
.star-node[data-star="images"] .star-dot { background: var(--mint-glow); box-shadow: 0 0 8px var(--mint-glow); }
|
||||
.star-node[data-star="images"] .star-visual::before {
|
||||
content: '✿'; position: absolute; color: var(--mint-glow); font-size: 10px; top: -12px; opacity: 0.4;
|
||||
}
|
||||
.star-node[data-star="images"] .star-visual::after {
|
||||
content: '✿'; position: absolute; color: var(--mint-glow); font-size: 10px; bottom: -12px; opacity: 0.4;
|
||||
}
|
||||
|
||||
/* Personality 5: Playlists (The Hearth) */
|
||||
.star-node[data-star="playlists"] .star-dot { background: var(--toucan-gold); box-shadow: 0 0 10px var(--toucan-gold); }
|
||||
.star-node[data-star="playlists"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 24px; height: 24px; border-radius: 50%;
|
||||
background: radial-gradient(circle, var(--fire-amber) 0%, transparent 70%);
|
||||
animation: hearth-glow 3s ease-in-out infinite;
|
||||
}
|
||||
@keyframes hearth-glow { 0%, 100% { opacity: 0.1; transform: scale(0.8); } 50% { opacity: 0.3; transform: scale(1.1); } }
|
||||
|
||||
/* Personality 6: Watchlists (The Nebula Point) */
|
||||
.star-node[data-star="watchlists"] .star-dot { background: var(--orchid); box-shadow: 0 0 8px var(--orchid); }
|
||||
.star-node[data-star="watchlists"] .star-visual::before {
|
||||
content: ''; position: absolute; width: 30px; height: 20px; border-radius: 50%;
|
||||
background: rgba(197, 88, 217, 0.1); filter: blur(4px);
|
||||
}
|
||||
|
||||
/* Personality 7: ToolsnToys (The Spark) */
|
||||
.star-node[data-star="toolsntoys"] .star-dot { background: var(--fairy-pink); box-shadow: 0 0 10px var(--fairy-pink); }
|
||||
.star-node[data-star="toolsntoys"] .star-visual::before {
|
||||
content: '+'; position: absolute; color: var(--fairy-pink); font-size: 18px; top: -14px; opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Personality 8: Creatorlists (The Flow) */
|
||||
.star-node[data-star="creatorlists"] .star-dot { background: var(--waterfall); box-shadow: 0 0 8px var(--waterfall); }
|
||||
.star-node[data-star="creatorlists"] .star-visual::before {
|
||||
content: ':::'; position: absolute; color: var(--waterfall); left: 24px; font-size: 10px; opacity: 0.4; letter-spacing: 2px;
|
||||
}
|
||||
|
||||
/* ── Transition Zone: Skyline ── */
|
||||
|
||||
#transition-zone {
|
||||
position: relative;
|
||||
width: 100%; height: 75vh;
|
||||
background: linear-gradient(to bottom,
|
||||
var(--bg-void) 0%,
|
||||
#080a14 30%,
|
||||
#0d0e1a 60%,
|
||||
var(--bg-warm) 100%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#skyline {
|
||||
position: absolute;
|
||||
bottom: 0; left: 0;
|
||||
width: 100%; height: 70%;
|
||||
display: flex; align-items: flex-end; justify-content: center;
|
||||
}
|
||||
|
||||
.building {
|
||||
background: #05070c;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(232, 148, 58, 0.05);
|
||||
}
|
||||
|
||||
.building.bio-orchid::before {
|
||||
content: ''; position: absolute; top: 10%; left: 0; width: 2px; height: 35%;
|
||||
background: var(--orchid); box-shadow: 0 0 6px var(--orchid); opacity: 0.12;
|
||||
}
|
||||
|
||||
.building.bio-mint::after {
|
||||
content: ''; position: absolute; top: 20%; right: 0; width: 1px; height: 45%;
|
||||
background: var(--mint-glow); box-shadow: 0 0 6px var(--mint-glow); opacity: 0.1;
|
||||
}
|
||||
|
||||
.billboard-nav {
|
||||
position: absolute;
|
||||
top: -2px; left: 50%;
|
||||
transform: translate(-50%, -100%);
|
||||
padding: 3px 10px;
|
||||
font-size: 13px; font-weight: 500;
|
||||
border: 1px solid;
|
||||
background: rgba(4, 6, 11, 0.95);
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.bb-teal { color: var(--neon-teal); border-color: rgba(42,196,179,0.25); }
|
||||
.bb-amber { color: var(--fire-amber); border-color: rgba(232,148,58,0.25); }
|
||||
.bb-orchid{ color: var(--orchid); border-color: rgba(197,88,217,0.25); }
|
||||
.bb-pink { color: var(--fairy-pink); border-color: rgba(244,114,182,0.25); }
|
||||
.bb-gold { color: var(--toucan-gold);border-color: rgba(255,207,64,0.25); }
|
||||
|
||||
.billboard-nav:hover {
|
||||
color: #fff; background: var(--fire-amber); border-color: var(--fire-amber);
|
||||
}
|
||||
|
||||
/* ── Lightbox: Campfire Note ── */
|
||||
|
||||
#lightbox-overlay {
|
||||
position: fixed; inset: 0;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
z-index: 10000;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
#lightbox-overlay.hidden { display: none; }
|
||||
|
||||
#lightbox {
|
||||
background: var(--bg-warm);
|
||||
border: 1px solid var(--fire-amber);
|
||||
border-top: 2px solid var(--phosphor);
|
||||
border-radius: 4px;
|
||||
padding: 40px;
|
||||
max-width: 500px; width: 90%;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#lightbox::after {
|
||||
content: ''; position: absolute; inset: 6px;
|
||||
border: 1px solid rgba(197, 88, 217, 0.12);
|
||||
pointer-events: none; border-radius: 2px;
|
||||
}
|
||||
|
||||
#lightbox p {
|
||||
font-size: 16px; line-height: 1.7;
|
||||
color: var(--text-warm); margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.nav-hint {
|
||||
font-size: 14px; color: var(--text-muted);
|
||||
margin-bottom: 30px; display: block;
|
||||
}
|
||||
|
||||
#lightbox-enter {
|
||||
padding: 10px 32px;
|
||||
font-size: 14px; font-weight: 600;
|
||||
color: var(--bg-void); background: var(--fire-amber);
|
||||
border: none; border-radius: 4px; cursor: pointer;
|
||||
transition: opacity 150ms;
|
||||
}
|
||||
#lightbox-enter:hover { opacity: 0.9; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="star-zone">
|
||||
<canvas id="nebula-canvas"></canvas>
|
||||
<canvas id="star-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="transition-zone">
|
||||
<div id="skyline"></div>
|
||||
</div>
|
||||
|
||||
<div id="lightbox-overlay" class="hidden">
|
||||
<div id="lightbox">
|
||||
<p>Hello traveller, welcome to a singular, particular space. Feel free to explore this little pocket of the universe. It's an adventure, bring snacks. Happy wanderings, Myster Wizzard</p>
|
||||
<span class="nav-hint">click stars to explore · arrow keys to navigate · escape to return</span>
|
||||
<button id="lightbox-enter">Enter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STARS = [
|
||||
{ id: 'writings', label: 'Writings', x: 25, y: 18 },
|
||||
{ id: 'videos', label: 'Videos', x: 68, y: 15 },
|
||||
{ id: 'music', label: 'Music', x: 12, y: 42 },
|
||||
{ id: 'images', label: 'Images', x: 55, y: 35 },
|
||||
{ id: 'playlists', label: 'Playlists', x: 78, y: 48 },
|
||||
{ id: 'watchlists', label: 'Watchlists', x: 22, y: 65 },
|
||||
{ id: 'toolsntoys', label: 'ToolsnToys', x: 50, y: 72 },
|
||||
{ id: 'creatorlists', label: 'Creatorlists', x: 75, y: 70 }
|
||||
];
|
||||
|
||||
const nebulaCanvas = document.getElementById('nebula-canvas');
|
||||
const starCanvas = document.getElementById('star-canvas');
|
||||
const nCtx = nebulaCanvas.getContext('2d');
|
||||
const sCtx = starCanvas.getContext('2d');
|
||||
let bgStars = [];
|
||||
|
||||
function resize() {
|
||||
nebulaCanvas.width = starCanvas.width = window.innerWidth;
|
||||
nebulaCanvas.height = starCanvas.height = window.innerHeight;
|
||||
drawNebulae();
|
||||
initStars();
|
||||
}
|
||||
|
||||
function drawNebulae() {
|
||||
nCtx.clearRect(0, 0, nebulaCanvas.width, nebulaCanvas.height);
|
||||
const w = nebulaCanvas.width, h = nebulaCanvas.height;
|
||||
|
||||
// BOLDER washes: Orchid, Paradise, Toucan, Teal, Pink, Purple
|
||||
const washes = [
|
||||
{ x: 0.2, y: 0.25, r: 0.5, c: 'rgba(197, 88, 217, 0.08)' }, // Orchid
|
||||
{ x: 0.8, y: 0.15, r: 0.6, c: 'rgba(255, 127, 63, 0.06)' }, // Paradise
|
||||
{ x: 0.5, y: 0.6, r: 0.5, c: 'rgba(255, 207, 64, 0.05)' }, // Toucan
|
||||
{ x: 0.1, y: 0.7, r: 0.5, c: 'rgba(42, 196, 179, 0.07)' }, // Teal
|
||||
{ x: 0.7, y: 0.8, r: 0.4, c: 'rgba(244, 114, 182, 0.06)' }, // Fairy Pink
|
||||
{ x: 0.4, y: 0.1, r: 0.4, c: 'rgba(74, 29, 110, 0.08)' } // Purple
|
||||
];
|
||||
|
||||
washes.forEach(wash => {
|
||||
const grad = nCtx.createRadialGradient(
|
||||
wash.x * w, wash.y * h, 0,
|
||||
wash.x * w, wash.y * h, wash.r * w
|
||||
);
|
||||
grad.addColorStop(0, wash.c);
|
||||
grad.addColorStop(1, 'transparent');
|
||||
nCtx.fillStyle = grad;
|
||||
nCtx.fillRect(0, 0, w, h);
|
||||
});
|
||||
}
|
||||
|
||||
function initStars() {
|
||||
bgStars = [];
|
||||
const colorPool = [
|
||||
'200,210,230', // Cool White
|
||||
'240,220,190', // Warm White
|
||||
'140,180,230', // Pale Blue
|
||||
'255,207,64', // Toucan Gold
|
||||
'244,114,182', // Fairy Pink
|
||||
'197,88,217', // Orchid
|
||||
'134,239,172', // Mint Green
|
||||
'212,101,74' // Coral
|
||||
];
|
||||
|
||||
const count = window.innerWidth < 480 ? 250 : 450;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const r = Math.random() < 0.05 ? 2.5 + Math.random() : (Math.random() < 0.7 ? 0.4 + Math.random() : 1.2 + Math.random());
|
||||
bgStars.push({
|
||||
x: Math.random() * starCanvas.width,
|
||||
y: Math.random() * starCanvas.height,
|
||||
r: r,
|
||||
color: colorPool[Math.floor(Math.random() * colorPool.length)],
|
||||
opacity: 0.3 + Math.random() * 0.5,
|
||||
speed: 0.4 + Math.random() * 0.8,
|
||||
phase: Math.random() * Math.PI * 2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function draw(time) {
|
||||
sCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);
|
||||
const t = time * 0.001;
|
||||
bgStars.forEach(s => {
|
||||
const a = s.opacity + Math.sin(t * s.speed + s.phase) * 0.2;
|
||||
sCtx.beginPath();
|
||||
sCtx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
|
||||
sCtx.fillStyle = `rgba(${s.color}, ${Math.max(0.1, Math.min(1, a))})`;
|
||||
sCtx.fill();
|
||||
});
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
// Nodes
|
||||
const starZone = document.getElementById('star-zone');
|
||||
STARS.forEach(s => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'star-node';
|
||||
btn.dataset.star = s.id;
|
||||
btn.style.left = s.x + '%';
|
||||
btn.style.top = s.y + '%';
|
||||
btn.innerHTML = `<div class="star-visual"><span class="star-dot"></span></div><span class="star-label">${s.label}</span>`;
|
||||
starZone.appendChild(btn);
|
||||
});
|
||||
|
||||
// Skyline
|
||||
function initSkyline() {
|
||||
const skyline = document.getElementById('skyline');
|
||||
const bbColors = ['bb-teal', 'bb-amber', 'bb-orchid', 'bb-pink', 'bb-gold'];
|
||||
const winColors = ['#e8943a', '#2ac4b3', '#c558d9', '#f472b6', '#00ff41'];
|
||||
|
||||
for (let i = 0; i < 42; i++) {
|
||||
const b = document.createElement('div');
|
||||
b.className = 'building';
|
||||
const bio = Math.random();
|
||||
if (bio > 0.9) b.classList.add('bio-orchid');
|
||||
else if (bio > 0.8) b.classList.add('bio-mint');
|
||||
|
||||
const w = 20 + Math.random() * 50;
|
||||
const h = 50 + Math.random() * 300;
|
||||
b.style.width = w + 'px';
|
||||
b.style.height = h + 'px';
|
||||
b.style.marginRight = '2px';
|
||||
|
||||
if (h > 100) {
|
||||
for (let j = 0; j < Math.floor(h/30); j++) {
|
||||
if (Math.random() > 0.6) continue;
|
||||
const win = document.createElement('div');
|
||||
const wc = winColors[Math.floor(Math.random()*winColors.length)];
|
||||
win.style.cssText = `position:absolute; width:2px; height:2px; background:${wc}; opacity:${0.1 + Math.random()*0.2}; left:${Math.random()*w}px; top:${20+j*25}px;`;
|
||||
b.appendChild(win);
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.random() > 0.85) {
|
||||
const bb = document.createElement('a');
|
||||
bb.className = 'billboard-nav ' + bbColors[Math.floor(Math.random()*bbColors.length)];
|
||||
bb.textContent = 'SIGNAL';
|
||||
bb.href = '#';
|
||||
b.appendChild(bb);
|
||||
}
|
||||
skyline.appendChild(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Lightbox
|
||||
const overlay = document.getElementById('lightbox-overlay');
|
||||
if (!localStorage.getItem('sp-welcomed')) overlay.classList.remove('hidden');
|
||||
document.getElementById('lightbox-enter').onclick = () => {
|
||||
overlay.classList.add('hidden');
|
||||
localStorage.setItem('sp-welcomed', 'true');
|
||||
};
|
||||
|
||||
window.onresize = resize;
|
||||
resize();
|
||||
initSkyline();
|
||||
requestAnimationFrame(draw);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,551 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Draft: Starfield & Nebula v1 - Gemini</title>
|
||||
<!--
|
||||
DRAFT: Starfield & Nebula v1
|
||||
AUTHOR: Gemini (Designer Agent)
|
||||
DATE: 2026-03-26
|
||||
|
||||
DESCRIPTION:
|
||||
This draft focuses on the celestial atmosphere.
|
||||
|
||||
NEW IN THIS VERSION:
|
||||
- Multi-colored stars (Amber, Teal, Blue, Magenta) with varied sizes.
|
||||
- Procedural "Nebula Washes" using large, low-opacity radial gradients on the canvas.
|
||||
- Differentiated Star Nodes: Each node has a unique glow color and subtle breathing animation.
|
||||
- Pulsing Constellation Lines: SVG lines now have a faint, organic pulse.
|
||||
- Enhanced Skyline: Added bioluminescent "moss" highlights and warmer window accents.
|
||||
- Campfire-style Lightbox: Warm amber tones and a focused layout.
|
||||
- Strictly follows Uncodixfy: No large radii, no big blurs, no glassmorphism.
|
||||
-->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Space+Grotesk:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
/* Deep Space Palette */
|
||||
--bg-void: #04060b;
|
||||
--bg-deep: #060a14;
|
||||
--bg-warm: #0d1320;
|
||||
|
||||
/* Celestial & Fire Palette */
|
||||
--fire-amber: #e8943a;
|
||||
--fire-coral: #d4654a;
|
||||
--neon-green: #32dc8c;
|
||||
--neon-teal: #2ac4b3;
|
||||
--deep-red: #8b2020;
|
||||
--cosmic-purple:#4a1d6e;
|
||||
--star-blue: #a0c4ff;
|
||||
|
||||
/* Text */
|
||||
--text-warm: #e8d5b8;
|
||||
--text-muted: #6a7a8a;
|
||||
|
||||
/* Constraints */
|
||||
--radius-std: 4px;
|
||||
--radius-max: 10px;
|
||||
--blur-max: 8px;
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg-void);
|
||||
color: var(--text-warm);
|
||||
overflow: hidden;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
body.content-mode {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* ── Zone 1: Star Map ── */
|
||||
|
||||
#star-zone {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(circle at 50% 50%, #080c18 0%, #04060b 100%);
|
||||
}
|
||||
|
||||
#star-canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#constellation-svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.constellation-line {
|
||||
stroke-width: 1;
|
||||
stroke-linecap: round;
|
||||
transition: stroke-opacity 1s ease;
|
||||
}
|
||||
|
||||
/* ── Star Nodes ── */
|
||||
|
||||
.star-node {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
outline: none;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.star-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 4px #fff;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.star-label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: lowercase;
|
||||
white-space: nowrap;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s ease, color 0.2s ease;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Node Specificity */
|
||||
.star-node[data-star="writings"] .star-dot { box-shadow: 0 0 6px var(--star-blue); background: var(--star-blue); }
|
||||
.star-node[data-star="videos"] .star-dot { box-shadow: 0 0 6px var(--fire-coral); background: var(--fire-coral); }
|
||||
.star-node[data-star="music"] .star-dot { box-shadow: 0 0 6px var(--neon-teal); background: var(--neon-teal); }
|
||||
.star-node[data-star="images"] .star-dot { box-shadow: 0 0 6px var(--neon-green); background: var(--neon-green); }
|
||||
.star-node[data-star="playlists"] .star-dot { box-shadow: 0 0 6px var(--fire-amber); background: var(--fire-amber); }
|
||||
.star-node[data-star="watchlists"] .star-dot { box-shadow: 0 0 6px var(--cosmic-purple); background: var(--cosmic-purple); }
|
||||
.star-node[data-star="toolsntoys"] .star-dot { box-shadow: 0 0 6px #fff; background: #fff; }
|
||||
.star-node[data-star="creatorlists"] .star-dot { box-shadow: 0 0 6px var(--text-warm); background: var(--text-warm); }
|
||||
|
||||
.star-node:hover .star-dot,
|
||||
.star-node:focus .star-dot,
|
||||
.star-node.current .star-dot {
|
||||
background: var(--fire-amber) !important;
|
||||
box-shadow: 0 0 8px var(--fire-amber) !important;
|
||||
}
|
||||
|
||||
.star-node:hover .star-label,
|
||||
.star-node:focus .star-label,
|
||||
.star-node.current .star-label {
|
||||
color: var(--text-warm);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.star-node.visited::after {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
right: -12px;
|
||||
font-size: 10px;
|
||||
color: var(--neon-green);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* ── Transition Zone: Skyline ── */
|
||||
|
||||
#transition-zone {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: linear-gradient(to bottom, var(--bg-void) 0%, #080c14 40%, #0d1320 100%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#skyline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.building {
|
||||
background: #05080f;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(232, 148, 58, 0.05);
|
||||
}
|
||||
|
||||
/* Bioluminescent Highlights */
|
||||
.building.bio-active::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: 0;
|
||||
width: 2px;
|
||||
height: 30%;
|
||||
background: var(--neon-teal);
|
||||
box-shadow: 0 0 6px var(--neon-teal);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.billboard-nav {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -100%);
|
||||
padding: 4px 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: var(--text-warm);
|
||||
border: 1px solid var(--text-muted);
|
||||
background: var(--bg-void);
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
transition: border-color 0.2s ease, color 0.2s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.billboard-nav:hover,
|
||||
.billboard-nav:focus {
|
||||
color: var(--fire-amber);
|
||||
border-color: var(--fire-amber);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* ── Zone 3: Content Alley ── */
|
||||
|
||||
#content-zone {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-warm);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content-frame {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
border: none;
|
||||
display: block;
|
||||
background: var(--bg-warm);
|
||||
}
|
||||
|
||||
/* ── Persistent UI ── */
|
||||
|
||||
#back-btn {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 100;
|
||||
padding: 8px 16px;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
background: rgba(4, 6, 11, 0.8);
|
||||
border: 1px solid rgba(106, 122, 138, 0.3);
|
||||
border-radius: var(--radius-std);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
#back-btn:hover {
|
||||
color: var(--fire-amber);
|
||||
border-color: var(--fire-amber);
|
||||
}
|
||||
|
||||
#jl-link {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 100;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
#jl-link:hover {
|
||||
opacity: 1;
|
||||
color: var(--fire-amber);
|
||||
}
|
||||
|
||||
/* ── Lightbox: Campfire Style ── */
|
||||
|
||||
#lightbox-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
z-index: 200;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#lightbox-overlay.hidden { display: none; }
|
||||
|
||||
#lightbox {
|
||||
background: var(--bg-warm);
|
||||
border: 1px solid var(--fire-amber);
|
||||
border-radius: var(--radius-std);
|
||||
padding: 40px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#lightbox::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 4px;
|
||||
border: 1px solid rgba(232, 148, 58, 0.1);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#lightbox p {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-warm);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.nav-hint {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 32px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#lightbox-enter {
|
||||
padding: 10px 32px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--bg-void);
|
||||
background: var(--fire-amber);
|
||||
border: none;
|
||||
border-radius: var(--radius-std);
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
#lightbox-enter:hover { opacity: 0.9; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="star-zone">
|
||||
<canvas id="star-canvas"></canvas>
|
||||
<svg id="constellation-svg" xmlns="http://www.w3.org/2000/svg"></svg>
|
||||
</div>
|
||||
|
||||
<div id="transition-zone">
|
||||
<div id="skyline"></div>
|
||||
</div>
|
||||
|
||||
<div id="content-zone">
|
||||
<iframe id="content-frame" title="Section content"></iframe>
|
||||
</div>
|
||||
|
||||
<button id="back-btn">stars</button>
|
||||
<a id="jl-link" href="https://jl-kruger.github.io/introductions" target="_blank" rel="noopener">JL Kruger</a>
|
||||
|
||||
<div id="lightbox-overlay" class="hidden">
|
||||
<div id="lightbox">
|
||||
<p>Hello traveller, welcome to a singular, particular space. Feel free to explore this little pocket of the universe. It's an adventure, bring snacks. Happy wanderings, Myster Wizzard</p>
|
||||
<span class="nav-hint">click stars · arrow keys · escape to return</span>
|
||||
<button id="lightbox-enter">Enter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STARS = [
|
||||
{ id: 'writings', label: 'Writings', x: 25, y: 22, color: '#a0c4ff' },
|
||||
{ id: 'videos', label: 'Videos', x: 65, y: 18, color: '#d4654a' },
|
||||
{ id: 'music', label: 'Music', x: 15, y: 45, color: '#2ac4b3' },
|
||||
{ id: 'images', label: 'Images', x: 50, y: 35, color: '#32dc8c' },
|
||||
{ id: 'playlists', label: 'Playlists', x: 80, y: 50, color: '#e8943a' },
|
||||
{ id: 'watchlists', label: 'Watchlists', x: 20, y: 70, color: '#4a1d6e' },
|
||||
{ id: 'toolsntoys', label: 'ToolsnToys', x: 55, y: 75, color: '#ffffff' },
|
||||
{ id: 'creatorlists', label: 'Creatorlists', x: 82, y: 72, color: '#e8d5b8' }
|
||||
];
|
||||
|
||||
const CONNECTIONS = [
|
||||
['writings', 'videos'], ['music', 'images'], ['images', 'videos'],
|
||||
['watchlists', 'toolsntoys'], ['toolsntoys', 'creatorlists'], ['music', 'watchlists']
|
||||
];
|
||||
|
||||
const canvas = document.getElementById('star-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
let bgStars = [];
|
||||
let nebulae = [];
|
||||
|
||||
function resize() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
initAtmosphere();
|
||||
}
|
||||
|
||||
function initAtmosphere() {
|
||||
bgStars = [];
|
||||
const colors = ['#ffffff', '#a0c4ff', '#ffd7ba', '#e8943a', '#2ac4b3'];
|
||||
for(let i=0; i<350; i++) {
|
||||
bgStars.push({
|
||||
x: Math.random() * canvas.width,
|
||||
y: Math.random() * canvas.height,
|
||||
r: Math.random() * 1.5 + 0.2,
|
||||
color: colors[Math.floor(Math.random()*colors.length)],
|
||||
opacity: Math.random() * 0.7 + 0.3,
|
||||
blink: Math.random() * 0.02 + 0.005,
|
||||
phase: Math.random() * Math.PI * 2
|
||||
});
|
||||
}
|
||||
|
||||
nebulae = [
|
||||
{ x: 0.2, y: 0.3, r: 0.4, color: 'rgba(74, 29, 110, 0.08)' },
|
||||
{ x: 0.8, y: 0.2, r: 0.5, color: 'rgba(42, 196, 179, 0.05)' },
|
||||
{ x: 0.5, y: 0.7, r: 0.6, color: 'rgba(232, 148, 58, 0.04)' }
|
||||
];
|
||||
}
|
||||
|
||||
function draw(time) {
|
||||
ctx.fillStyle = '#04060b';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Draw Nebulae
|
||||
nebulae.forEach(n => {
|
||||
const grad = ctx.createRadialGradient(
|
||||
n.x * canvas.width, n.y * canvas.height, 0,
|
||||
n.x * canvas.width, n.y * canvas.height, n.r * canvas.width
|
||||
);
|
||||
grad.addColorStop(0, n.color);
|
||||
grad.addColorStop(1, 'transparent');
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
});
|
||||
|
||||
// Draw Stars
|
||||
const t = time * 0.001;
|
||||
bgStars.forEach(s => {
|
||||
const o = s.opacity + Math.sin(t / s.blink + s.phase) * 0.2;
|
||||
ctx.beginPath();
|
||||
ctx.arc(s.x, s.y, s.r, 0, Math.PI*2);
|
||||
ctx.fillStyle = s.color;
|
||||
ctx.globalAlpha = Math.max(0.1, Math.min(1, o));
|
||||
ctx.fill();
|
||||
});
|
||||
ctx.globalAlpha = 1;
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
// Star Nodes
|
||||
const starZone = document.getElementById('star-zone');
|
||||
STARS.forEach((s, i) => {
|
||||
const node = document.createElement('button');
|
||||
node.className = 'star-node';
|
||||
node.dataset.star = s.id;
|
||||
node.style.left = s.x + '%';
|
||||
node.style.top = s.y + '%';
|
||||
node.innerHTML = `<span class="star-dot"></span><span class="star-label">${s.label}</span>`;
|
||||
starZone.appendChild(node);
|
||||
});
|
||||
|
||||
// Constellations
|
||||
const svg = document.getElementById('constellation-svg');
|
||||
function drawLines() {
|
||||
svg.innerHTML = '';
|
||||
CONNECTIONS.forEach(pair => {
|
||||
const s1 = STARS.find(s => s.id === pair[0]);
|
||||
const s2 = STARS.find(s => s.id === pair[1]);
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', s1.x + '%');
|
||||
line.setAttribute('y1', s1.y + '%');
|
||||
line.setAttribute('x2', s2.x + '%');
|
||||
line.setAttribute('y2', s2.y + '%');
|
||||
line.setAttribute('class', 'constellation-line');
|
||||
line.setAttribute('stroke', s1.color);
|
||||
line.setAttribute('stroke-opacity', '0.15');
|
||||
svg.appendChild(line);
|
||||
});
|
||||
}
|
||||
|
||||
// Skyline
|
||||
function initSkyline() {
|
||||
const skyline = document.getElementById('skyline');
|
||||
for(let i=0; i<40; i++) {
|
||||
const b = document.createElement('div');
|
||||
b.className = 'building' + (Math.random() > 0.7 ? ' bio-active' : '');
|
||||
const w = 20 + Math.random() * 60;
|
||||
const h = 40 + Math.random() * 300;
|
||||
b.style.width = w + 'px';
|
||||
b.style.height = h + 'px';
|
||||
b.style.marginRight = '2px';
|
||||
|
||||
// Random Windows
|
||||
if(h > 100) {
|
||||
for(let j=0; j<Math.floor(h/40); j++) {
|
||||
const win = document.createElement('div');
|
||||
win.style.cssText = `position:absolute; width:2px; height:2px; background:var(--fire-amber); opacity:${Math.random()*0.2}; left:${Math.random()*w}px; top:${30+j*30}px;`;
|
||||
b.appendChild(win);
|
||||
}
|
||||
}
|
||||
skyline.appendChild(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Interaction
|
||||
const enterBtn = document.getElementById('lightbox-enter');
|
||||
const overlay = document.getElementById('lightbox-overlay');
|
||||
enterBtn.onclick = () => overlay.classList.add('hidden');
|
||||
|
||||
window.onresize = resize;
|
||||
resize();
|
||||
drawLines();
|
||||
initSkyline();
|
||||
requestAnimationFrame(draw);
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user