style: candlelit glow background replaces star field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 14:52:27 -04:00
parent e83c69c6c2
commit ba2c698801
+10 -111
View File
@@ -41,10 +41,15 @@ a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }
code { font-family: ui-monospace, monospace; font-size: 0.875em; background: var(--bg-elevated); padding: 0.1em 0.35em; border-radius: 3px; }
/* Star field */
#star-field { position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }
@keyframes star-orbit { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes star-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
#candle-glow {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
background:
radial-gradient(ellipse 80% 60% at 50% 40%, rgba(200, 168, 64, 0.045) 0%, transparent 70%),
radial-gradient(ellipse 50% 40% at 20% 80%, rgba(200, 168, 64, 0.025) 0%, transparent 65%);
}
/* Nav */
nav {
@@ -177,8 +182,7 @@ textarea { resize: vertical; }
</head>
<body>
{# Star field — orbits around top-left corner, populated by JS below #}
<div id="star-field"></div>
<div id="candle-glow"></div>
{% if session.user_id is defined %}
<nav>
@@ -243,111 +247,6 @@ function setTimeRange(val) {
{% block content %}{% endblock %}
</main>
<script>
(function () {
var field = document.getElementById('star-field');
if (!field) return;
var W = window.innerWidth;
var H = window.innerHeight;
var maxR = Math.sqrt(W * W + H * H);
// Subtle purple glow anchoring the field to the top-left corner
var glow = document.createElement('div');
glow.style.cssText = 'position:absolute;width:500px;height:500px;left:-250px;top:-250px;border-radius:50%;background:radial-gradient(circle,rgba(124,94,244,0.06) 0%,transparent 65%);pointer-events:none;';
field.appendChild(glow);
// Compute polygon points for a 5-pointed star inside a size×size box
function starPoints(size) {
var cx = size / 2, cy = size / 2;
var R = size / 2 * 0.95; // outer radius
var r = R * 0.382; // inner radius (golden ratio)
var pts = [];
for (var i = 0; i < 5; i++) {
var oa = (i * 72 - 90) * Math.PI / 180;
var ia = (i * 72 - 90 + 36) * Math.PI / 180;
pts.push((cx + R * Math.cos(oa)).toFixed(2) + ',' + (cy + R * Math.sin(oa)).toFixed(2));
pts.push((cx + r * Math.cos(ia)).toFixed(2) + ',' + (cy + r * Math.sin(ia)).toFixed(2));
}
return pts.join(' ');
}
// 22 wizard-hat stars: [size(px), opacity, isGold, orbitDuration(s), spinDuration(s)]
var defs = [
[230, 0.09, true, 200, 28],
[144, 0.08, true, 260, 40],
[ 92, 0.10, false, 150, 22],
[190, 0.07, true, 310, 35],
[116, 0.09, false, 175, 18],
[260, 0.07, true, 280, 45],
[ 80, 0.11, false, 135, 20],
[164, 0.08, true, 230, 32],
[104, 0.09, false, 165, 24],
[200, 0.07, true, 295, 38],
[ 70, 0.10, false, 120, 16],
[150, 0.08, true, 245, 30],
[ 88, 0.09, false, 140, 21],
[210, 0.07, true, 320, 42],
[128, 0.08, false, 180, 26],
[ 76, 0.10, true, 160, 19],
[175, 0.07, true, 290, 36],
[ 96, 0.09, false, 155, 23],
[220, 0.07, true, 305, 44],
[110, 0.08, false, 170, 25],
[ 84, 0.09, true, 235, 31],
[140, 0.08, false, 185, 27],
];
var n = defs.length;
defs.forEach(function (def, i) {
var size = def[0], opacity = def[1], isGold = def[2], orbitDur = def[3], spinDur = def[4];
// Spread evenly across a ~110° fan from top-left, small random jitter
var angleDeg = 4 + (i / (n - 1)) * 108 + (Math.random() * 8 - 4);
var angle = angleDeg * Math.PI / 180;
var radius = (0.15 + (i / n) * 0.7 + Math.random() * 0.15) * maxR * 0.88 + 60;
// Star center position in parent coords
var cx = Math.cos(angle) * radius;
var cy = Math.sin(angle) * radius;
var left = cx - size / 2;
var top = cy - size / 2;
var orbitDelay = -(Math.random() * orbitDur);
var spinDelay = -(Math.random() * spinDur);
var color = isGold ? '#c9a84c' : '#c8b4f8';
// Outer wrapper handles orbit — transform-origin points back to (0,0) corner
var wrapper = document.createElement('div');
wrapper.style.cssText = [
'position:absolute',
'left:' + left + 'px',
'top:' + top + 'px',
'width:' + size + 'px',
'height:'+ size + 'px',
'opacity:' + opacity,
'transform-origin:' + (-left) + 'px ' + (-top) + 'px',
'animation:star-orbit ' + orbitDur + 's ' + orbitDelay + 's linear infinite',
'pointer-events:none'
].join(';');
// Inner SVG handles spin — transform-origin defaults to 50% 50% (star center)
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', size);
svg.setAttribute('height', size);
svg.setAttribute('viewBox', '0 0 ' + size + ' ' + size);
svg.style.cssText = 'display:block;animation:star-spin ' + spinDur + 's ' + spinDelay + 's linear infinite;';
var poly = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
poly.setAttribute('points', starPoints(size));
poly.setAttribute('fill', color);
svg.appendChild(poly);
wrapper.appendChild(svg);
field.appendChild(wrapper);
});
}());
</script>
{% block extra_scripts %}{% endblock %}
</body>