radiance: new home page — WebGL orb hero, DG cube loader, white dropdown menu

Replaces the Crush landing page with a single-screen hero (no scroll):
gradient sky, particle orb with corona, 'Welcome to dangrubb.net' title,
top-left DG logo and a numbered menu. Raw WebGL (no three.js), self-hosted
Instrument Sans + Geist Mono. ~10 KB of JS.
This commit is contained in:
dangrubbb
2026-10-22 20:00:53 -04:00
parent 3a662c8498
commit ecaa3bbf6a
7 changed files with 714 additions and 174 deletions

View File

@ -1,182 +1,97 @@
---
import CrushBase from '../layouts/CrushBase.astro';
import '@fontsource/instrument-sans/latin-400.css';
import '@fontsource/instrument-sans/latin-500.css';
import '@fontsource/geist-mono/latin-500.css';
import '../styles/radiance.css';
const nav = [
{ label: 'Intelligence Platform', href: 'https://ai.dangrubb.net' },
{ label: 'Exclusive Music', href: '/music' },
{ label: 'Multimedia Entertainment', href: 'https://pi.dangrubb.net/jellyfin' },
{ label: 'Crypto', href: '#' },
{ label: 'Storage Solutions', href: 'https://pi.dangrubb.net/nextcloud' },
];
const links = [
{ label: 'Blog', href: '/blog' },
{ label: 'CV', href: '/cv' },
{ label: 'Git', href: 'https://pi.dangrubb.net/dangit' },
];
---
<CrushBase title="dangrubb.net">
<div class="crush-page">
<header class="top-banner">
<div class="brand">
<span class="brand-name">dangrubb</span><span class="brand-dot">.</span><span class="brand-tld">net</span>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>dangrubb.net</title>
<meta name="description" content="Welcome to dangrubb.net" />
<meta name="theme-color" content="#fff6f4" />
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon" />
<link rel="preload" as="image" href="/src/img/DanGrubbLogoWhite.png" />
</head>
<body class="is-loading">
<div class="loader" id="loader" aria-hidden="true">
<div class="loader__stage">
<div class="scene">
<div class="cube">
<div class="cube__face cube__face--front"><img src="/src/img/DanGrubbLogoWhite.png" alt="" width="140" height="140" /></div>
<div class="cube__face cube__face--back"><img src="/src/img/DanGrubbLogoWhite.png" alt="" width="140" height="140" /></div>
<div class="cube__face cube__face--right"></div>
<div class="cube__face cube__face--left"></div>
<div class="cube__face cube__face--top"></div>
<div class="cube__face cube__face--bottom"></div>
</div>
</div>
</div>
<p class="tagline">OFFICIAL SITE</p>
<p class="loader__count" id="loader-count">000%</p>
</div>
<header class="bar">
<a class="bar__logo" href="/">
<span class="sr-only">dangrubb.net home</span>
<img src="/src/img/DanGrubbLogoDark.png" alt="" width="48" height="48" />
</a>
<nav class="menu" id="menu" aria-label="Site">
<button class="menu__btn" id="menu-btn" type="button" aria-expanded="false" aria-controls="menu-panel">
<span class="sr-only">Site navigation</span>
<svg class="menu__icon menu__icon--open" viewBox="0 0 18 14" width="18" height="14" aria-hidden="true">
<path d="M0 1h2M5 1h13M0 7h10M13 7h5M0 13h2M5 13h13" stroke="currentColor" stroke-width="1.5" fill="none" />
</svg>
<svg class="menu__icon menu__icon--close" viewBox="0 0 18 18" width="18" height="18" aria-hidden="true">
<path d="M1 1l16 16M17 1L1 17" stroke="currentColor" stroke-width="1.5" fill="none" />
</svg>
</button>
<div class="menu__panel" id="menu-panel">
<ul class="menu__list">
{nav.map((item, i) => (
<li>
<a href={item.href}>
<span class="menu__num">{String(i + 1).padStart(2, '0')}</span>
<span class="menu__label">{item.label}</span>
</a>
</li>
))}
</ul>
<div class="menu__links">
{links.map((l) => (
<a class="menu__link" href={l.href}><span>{l.label}</span></a>
))}
</div>
</div>
</nav>
</header>
<main class="logo-section">
<img src="/src/img/pack-splatter.png" alt="" class="splatter-img">
<div class="logo-center">
<img src="/src/img/DanGrubbLogoTeal.png" alt="DanGrubb" class="logo-img">
</div>
<main class="hero">
<canvas class="hero__orb" id="orb" aria-hidden="true"></canvas>
<h1 class="hero__title" id="title">Welcome to dangrubb.net</h1>
</main>
<footer class="bottom-nav">
<a href="https://ai.dangrubb.net" class="nav-item">AI</a>
<span class="nav-dot">•</span>
<a href="/blog" class="nav-item">BLOG</a>
<span class="nav-dot">•</span>
<a href="/music" class="nav-item">MUSIC</a>
<span class="nav-dot">•</span>
<a href="https://pi.dangrubb.net/jellyfin" class="nav-item">MEDIA</a>
<span class="nav-dot">•</span>
<a href="https://pi.dangrubb.net/nextcloud" class="nav-item">STORAGE</a>
<span class="nav-dot">•</span>
<a href="/cv" class="nav-item">CV</a>
<span class="nav-dot">•</span>
<a href="https://pi.dangrubb.net/dangit" class="nav-item">GIT</a>
</footer>
</div>
</CrushBase>
<script>
import { startOrb } from '../scripts/orb.js';
import { initUI } from '../scripts/ui.js';
<style>
.crush-page {
display: flex;
flex-direction: column;
height: 100vh;
height: 100dvh;
margin: 0;
background: var(--crush-white);
}
.top-banner {
text-align: center;
padding: 16px 20px 10px;
background: linear-gradient(180deg, #e8f5f5 0%, transparent 100%);
border-bottom: 3px solid var(--crush-teal);
flex-shrink: 0;
}
.brand {
font-family: 'Alfa Slab One', 'Georgia', serif;
font-size: clamp(3rem, 10vw, 5rem);
color: var(--crush-teal);
letter-spacing: -2px;
line-height: 1;
}
.brand-dot { color: var(--crush-teal-light); }
.brand-tld { color: var(--crush-teal-dark); }
.tagline {
font-size: 14px;
font-weight: 700;
letter-spacing: 4px;
color: var(--crush-teal);
margin-top: 8px;
text-transform: uppercase;
opacity: 0.8;
}
.logo-section {
flex: 1;
position: relative;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
min-height: 0;
}
.splatter-img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: contain;
pointer-events: none;
}
.logo-center {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.logo-img {
width: 12%;
max-width: 160px;
aspect-ratio: 1;
object-fit: contain;
filter: drop-shadow(0 3px 8px rgba(0, 102, 102, 0.3));
}
.bottom-nav {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
padding: 20px 20px 28px;
background: linear-gradient(0deg, #e8f5f5 0%, transparent 100%);
border-top: 3px solid var(--crush-teal);
flex-shrink: 0;
}
.nav-item {
font-size: 18px;
font-weight: 700;
color: var(--crush-teal);
letter-spacing: 2px;
padding: 8px 16px;
border-radius: 4px;
background: rgba(0, 139, 139, 0.05);
transition: all 0.3s ease;
}
.nav-item:hover {
background: rgba(0, 139, 139, 0.15);
color: var(--crush-teal-dark);
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(0, 139, 139, 0.2);
}
.nav-dot {
font-size: 20px;
color: var(--crush-teal);
opacity: 0.5;
}
@media (max-width: 480px) {
.brand { font-size: 2.5rem; }
.top-banner {
flex: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12px 15px;
}
.logo-section {
aspect-ratio: 3 / 4;
flex: none;
}
.splatter-img {
object-fit: cover;
}
.logo-img { width: 36%; }
.nav-item { font-size: 16px; padding: 8px 14px; }
.bottom-nav {
flex: 1;
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 3px;
padding: 4px 12px;
}
.nav-dot { display: none; }
}
</style>
initUI(startOrb);
</script>
</body>
</html>