<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Domain</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=Bebas+Neue&display=swap" rel="stylesheet" />
<style>
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--bg: #05080f;
--glow-color: #4af0ff;
--text-color: #e8f8ff;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
background-color: var(--bg);
}
body::before {
content: '';
position: fixed;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E");
background-size: 256px 256px;
pointer-events: none;
z-index: 10;
opacity: 0.35;
}
body::after {
content: '';
position: fixed;
inset: 0;
background: radial-gradient(ellipse at center, transparent 40%, #05080f 100%);
pointer-events: none;
z-index: 5;
}
.stage {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}
.domain {
display: block;
white-space: nowrap;
font-family: 'Bebas Neue', sans-serif;
font-size: 10px;
line-height: 1;
letter-spacing: 0.04em;
color: var(--text-color);
user-select: none;
animation: pulse 3.6s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
text-shadow:
0 0 18px rgba(74, 240, 255, 0.25),
0 0 45px rgba(74, 240, 255, 0.18),
0 0 90px rgba(74, 240, 255, 0.10),
0 0 160px rgba(74, 240, 255, 0.06);
opacity: 0.92;
}
50% {
text-shadow:
0 0 24px rgba(74, 240, 255, 0.55),
0 0 70px rgba(74, 240, 255, 0.38),
0 0 130px rgba(74, 240, 255, 0.22),
0 0 220px rgba(74, 240, 255, 0.10);
opacity: 1;
}
}
.stage {
animation: fadein 1.2s ease both;
}
@keyframes fadein {
from { opacity: 0; transform: scale(0.97); }
to { opacity: 1; transform: scale(1); }
}
</style>
<style>
#starfield {
position: fixed;
inset: 0;
z-index: 0;
}
.stage { z-index: 1; }
</style>
</head>
<body>
<canvas id="starfield"></canvas>
<div class="stage">
<span class="domain" id="domain"></span>
</div>
<script>
const el = document.getElementById('domain');
const hostname = window.location.hostname || 'localhost';
el.textContent = hostname;
document.title = hostname;
function fitText() {
const padding = 32;
const available = window.innerWidth - padding * 2;
let lo = 1, hi = window.innerHeight * 2;
el.style.fontSize = hi + 'px';
while (hi - lo > 0.5) {
const mid = (lo + hi) / 2;
el.style.fontSize = mid + 'px';
if (el.scrollWidth <= available) {
lo = mid;
} else {
hi = mid;
}
}
el.style.fontSize = lo + 'px';
}
fitText();
window.addEventListener('resize', fitText);
</script>
<script>
const canvas = document.getElementById('starfield');
const ctx = canvas.getContext('2d');
const STAR_COUNT = 320;
const SHOOTER_MAX = 4;
let W, H;
function resize() {
W = canvas.width = window.innerWidth;
H = canvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
function randBetween(a, b) { return a + Math.random() * (b - a); }
const stars = Array.from({ length: STAR_COUNT }, () => ({
x: Math.random(),
y: Math.random(),
r: randBetween(0.3, 1.6),
baseAlpha: randBetween(0.25, 0.9),
alpha: 0,
phase: Math.random() * Math.PI * 2,
speed: randBetween(0.4, 1.8),
hue: Math.random() < 0.15 ? (Math.random() < 0.5 ? 200 : 40) : 0,
sat: Math.random() < 0.15 ? 80 : 0,
}));
class Shooter {
constructor() { this.reset(true); }
reset(initial = false) {
const edge = Math.random();
if (edge < 0.6) {
this.x = Math.random() * W;
this.y = -10;
} else {
this.x = -10;
this.y = Math.random() * H * 0.5;
}
const angle = randBetween(25, 55) * Math.PI / 180;
const speed = randBetween(420, 900);
this.vx = Math.cos(angle) * speed;
this.vy = Math.sin(angle) * speed;
this.len = randBetween(80, 220);
this.width = randBetween(1, 2.2);
this.life = 1;
this.decay = randBetween(0.55, 1.1);
this.delay = initial ? randBetween(0, 6) : randBetween(0.5, 5);
this.active = !initial;
}
update(dt) {
if (!this.active) {
this.delay -= dt;
if (this.delay <= 0) this.active = true;
return;
}
this.x += this.vx * dt;
this.y += this.vy * dt;
this.life -= this.decay * dt;
if (this.life <= 0 || this.x > W + 50 || this.y > H + 50) {
this.reset();
}
}
draw(ctx) {
if (!this.active) return;
const tx = this.x - (this.vx / Math.hypot(this.vx, this.vy)) * this.len;
const ty = this.y - (this.vy / Math.hypot(this.vx, this.vy)) * this.len;
const grad = ctx.createLinearGradient(tx, ty, this.x, this.y);
grad.addColorStop(0, `rgba(255,255,255,0)`);
grad.addColorStop(0.6, `rgba(200,240,255,${(this.life * 0.4).toFixed(3)})`);
grad.addColorStop(1, `rgba(255,255,255,${(this.life * 0.9).toFixed(3)})`);
ctx.save();
ctx.beginPath();
ctx.moveTo(tx, ty);
ctx.lineTo(this.x, this.y);
ctx.strokeStyle = grad;
ctx.lineWidth = this.width * this.life;
ctx.lineCap = 'round';
ctx.stroke();
ctx.beginPath();
ctx.arc(this.x, this.y, this.width * 1.4 * this.life, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255,255,255,${(this.life * 0.85).toFixed(3)})`;
ctx.fill();
ctx.restore();
}
}
const shooters = Array.from({ length: SHOOTER_MAX }, () => new Shooter());
let last = null;
function frame(ts) {
if (!last) last = ts;
const dt = Math.min((ts - last) / 1000, 0.1);
last = ts;
ctx.clearRect(0, 0, W, H);
const now = ts / 1000;
for (const s of stars) {
s.alpha = s.baseAlpha * (0.4 + 0.6 * (0.5 + 0.5 * Math.sin(now * s.speed * Math.PI * 2 + s.phase)));
ctx.beginPath();
ctx.arc(s.x * W, s.y * H, s.r, 0, Math.PI * 2);
ctx.fillStyle = s.sat > 0
? `hsla(${s.hue},${s.sat}%,90%,${s.alpha.toFixed(3)})`
: `rgba(255,255,255,${s.alpha.toFixed(3)})`;
ctx.fill();
}
for (const sh of shooters) {
sh.update(dt);
sh.draw(ctx);
}
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
</script>
</body>
</html>