.wrap{position:relative;width:100%;height:100%}
#cv{position:absolute;inset:0;width:100%;height:100%}
.tag{position:absolute;top:8px;left:8px;z-index:2;font-size:10.5px;font-weight:700;color:#f1f0ec;
padding:5px 9px;border-radius:8px;background:rgba(13,13,18,0.55);border:1px solid rgba(255,255,255,0.15)}
const cv = document.getElementById('cv'), ctx = cv.getContext('2d');
const tag = document.getElementById('tag');
function fit() { const dpr = Math.min(devicePixelRatio || 1, 2); cv.width = innerWidth * dpr; cv.height = innerHeight * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); }
addEventListener('resize', fit); fit();
function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
let layers = [], sun = null;
function computeLayout(w, h) {
const r = mulberry32(21);
layers = [];
for (let l = 0; l < 3; l++) {
const pts = [];
for (let i = 0; i <= 7; i++) { const x = w * i / 7; const y = h * (0.5 + l * 0.14) - r() * h * 0.12; pts.push([x, y]); }
layers.push(pts);
}
sun = [w * (0.3 + r() * 0.4), h * (0.2 + r() * 0.1)];
}
function drawPath(pts, h) { ctx.beginPath(); ctx.moveTo(0, h); pts.forEach(([x, y]) => ctx.lineTo(x, y)); ctx.lineTo(pts[pts.length - 1][0], h); ctx.closePath(); }
function stylePastel(w, h) {
ctx.fillStyle = 'hsl(210 40% 88%)'; ctx.fillRect(0, 0, w, h);
ctx.beginPath(); ctx.arc(sun[0], sun[1], Math.min(w, h) * 0.08, 0, Math.PI * 2); ctx.fillStyle = 'hsl(45 70% 80%)'; ctx.fill();
layers.forEach((pts, l) => { drawPath(pts, h); ctx.fillStyle = 'hsl(' + (200 - l * 30) + ' 35% ' + (75 - l * 15) + '%)'; ctx.fill(); });
}
function styleInk(w, h) {
ctx.fillStyle = '#111116'; ctx.fillRect(0, 0, w, h);
ctx.strokeStyle = '#f1f0ec'; ctx.lineWidth = 1.4;
ctx.beginPath(); ctx.arc(sun[0], sun[1], Math.min(w, h) * 0.08, 0, Math.PI * 2); ctx.stroke();
layers.forEach((pts, l) => {
ctx.beginPath(); ctx.moveTo(pts[0][0], pts[0][1]); pts.forEach(([x, y]) => ctx.lineTo(x, y)); ctx.stroke();
ctx.strokeStyle = 'rgba(241,240,236,' + (0.35 - l * 0.08) + ')'; ctx.lineWidth = 0.8;
for (let x = 0; x < w; x += 10) { ctx.beginPath(); ctx.moveTo(x, h * (0.62 + l * 0.14)); ctx.lineTo(x - 10, h); ctx.stroke(); }
ctx.strokeStyle = '#f1f0ec'; ctx.lineWidth = 1.4;
});
}
function styleNeon(w, h) {
ctx.fillStyle = '#08060f'; ctx.fillRect(0, 0, w, h);
ctx.shadowColor = 'hsl(300 90% 60%)'; ctx.shadowBlur = 14;
ctx.strokeStyle = 'hsl(300 90% 65%)'; ctx.lineWidth = 2;
ctx.beginPath(); ctx.arc(sun[0], sun[1], Math.min(w, h) * 0.08, 0, Math.PI * 2); ctx.stroke();
layers.forEach((pts, l) => { ctx.shadowColor = 'hsl(' + (180 + l * 40) + ' 90% 60%)'; ctx.strokeStyle = 'hsl(' + (180 + l * 40) + ' 90% 65%)'; ctx.beginPath(); ctx.moveTo(pts[0][0], pts[0][1]); pts.forEach(([x, y]) => ctx.lineTo(x, y)); ctx.stroke(); });
ctx.shadowBlur = 0;
}
const styles = [{ fn: stylePastel, name: '파스텔' }, { fn: styleInk, name: '잉크 라인' }, { fn: styleNeon, name: '네온 글로우' }];
let si = 0;
function render() {
const w = innerWidth, h = innerHeight;
computeLayout(w, h);
styles[si].fn(w, h);
tag.textContent = 'LoRA: ' + styles[si].name;
}
render();
setInterval(() => { si = (si + 1) % styles.length; render(); }, 2600);