sin-titulo

Pasted Oct 8, 2026, 11:51 PM1 file126 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgt0rx7v9sakbmq
sin-titulo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#090014">
<title>Galaxia morada ✨ Flor de partículas</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Indie+Flower&display=swap');
:root{--lav:#ead6ff;--violet:#a855f7;--deep:#090014}
*{box-sizing:border-box}
html,body{margin:0;width:100%;height:100%;overflow:hidden;background:var(--deep);color:var(--lav)}
body{font-family:'Indie Flower','Segoe Print',cursive}
canvas{position:fixed;inset:0;width:100%;height:100%;display:block}
#title{position:fixed;z-index:2;top:22px;left:12px;right:12px;text-align:center;font-size:clamp(1.5rem,4vw,2.7rem);font-weight:normal;text-shadow:0 0 10px #c084fc,0 0 24px #7e22ce;pointer-events:none}
#hint{position:fixed;z-index:2;left:12px;right:12px;bottom:18px;text-align:center;font-size:1rem;color:#d8b4fe;text-shadow:0 0 9px #a855f7;pointer-events:none}
#letterBtn{position:fixed;z-index:5;right:20px;bottom:52px;width:58px;height:58px;border:0;border-radius:50%;font-size:1.55rem;background:linear-gradient(135deg,#6d28d9,#c084fc);box-shadow:0 0 22px #a855f7aa;cursor:pointer;animation:pulse 1.7s infinite}
@keyframes pulse{50%{transform:scale(1.08)}}
#overlay{position:fixed;z-index:10;inset:0;display:none;align-items:center;justify-content:center;padding:20px;background:#080014d9;backdrop-filter:blur(7px)}
#overlay.show{display:flex}
#card{position:relative;width:min(600px,100%);max-height:82vh;overflow:auto;padding:34px 26px;border:1px solid #c084fc88;border-radius:22px;background:linear-gradient(150deg,#2e1050f5,#10051ff7);box-shadow:0 0 40px #a855f755;color:#f3e8ff}
#card h2{text-align:center;margin:0 0 18px;font-size:2rem;text-shadow:0 0 12px #a855f7}
#card p{font-size:1.15rem;line-height:1.7;margin:0 0 14px}
#close{position:absolute;right:12px;top:8px;background:none;border:0;color:#e9d5ff;font-size:1.5rem;cursor:pointer}
#editNote{display:block;text-align:center;color:#c4b5fd;font:12px system-ui;margin-top:18px}
@media(max-width:480px){#title{top:18px}#card{padding:30px 20px}#card p{font-size:1.05rem}#letterBtn{bottom:48px;right:14px}}
@media(prefers-reduced-motion:reduce){#letterBtn{animation:none}}
</style>
</head>
<body>
<canvas id="space" aria-label="Galaxia morada animada con una flor de partículas"></canvas>
<h1 id="title">Feliz Día de las Flores Moradas 🪻</h1>
<div id="hint">Una flor hecha de estrellas, solo para ti 💜</div>
<button id="letterBtn" aria-label="Abrir carta">💌</button>
<div id="overlay" role="dialog" aria-modal="true" aria-labelledby="letterTitle">
  <section id="card">
    <button id="close" aria-label="Cerrar">×</button>
    <h2 id="letterTitle">Para ti 💜</h2>
    <div id="letterBody">
      <p>Hay personas que llegan y, sin darse cuenta, hacen que muchos de tus días sean mejores. Así eres tú para mí.</p>
      <p>Gracias por cada momento compartido, por las risas y por estar ahí incluso en lo simple. Quiero que sepas cuánto vales y cuánto significas para mí.</p>
      <p>Que esta flor morada te recuerde, hoy y siempre, lo especial que eres. 🌷💜</p>
    </div>
    <small id="editNote">Puedes personalizar este mensaje editando el texto dentro de <b>letterBody</b> en el archivo HTML.</small>
  </section>
</div>
<script>
(() => {
  const canvas = document.getElementById('space');
  const ctx = canvas.getContext('2d');
  let w, h, dpr, stars = [], dust = [], flower = [], t = 0;
  const rand = (a,b) => Math.random()*(b-a)+a;
  function resize(){
    dpr = Math.min(window.devicePixelRatio || 1, 2);
    w = innerWidth; h = innerHeight;
    canvas.width = Math.round(w*dpr); canvas.height = Math.round(h*dpr);
    ctx.setTransform(dpr,0,0,dpr,0,0);
    stars = Array.from({length:Math.min(420,Math.floor(w*h/2300))},()=>({
      x:Math.random()*w,y:Math.random()*h,r:rand(.35,1.7),a:rand(.25,.95),p:rand(0,Math.PI*2),speed:rand(.3,1.5)
    }));
    dust = Array.from({length:170},()=>({a:rand(0,Math.PI*2),r:rand(35,Math.min(w,h)*.46),s:rand(.001,.009),size:rand(.5,2)}));
    flower = [];
    // Pétalos en forma de flor, construidos con partículas.
    const petals = 8, points = 1500;
    for(let i=0;i<points;i++){
      const u = Math.random()*Math.PI*2;
      const radius = Math.abs(Math.cos(petals*u/2))*Math.min(w,h)*.19 * rand(.78,1.04);
      flower.push({a:u,r:radius,size:rand(.65,1.9),phase:rand(0,6.28),color:Math.random()});
    }
  }
  function glowDot(x,y,r,color,alpha=1){
    ctx.globalAlpha=alpha; ctx.fillStyle=color; ctx.shadowBlur=r*5; ctx.shadowColor=color;
    ctx.beginPath();ctx.arc(x,y,r,0,Math.PI*2);ctx.fill();ctx.shadowBlur=0;ctx.globalAlpha=1;
  }
  function draw(){
    t += .008;
    ctx.clearRect(0,0,w,h);
    const bg=ctx.createRadialGradient(w*.5,h*.5,0,w*.5,h*.5,Math.max(w,h)*.72);
    bg.addColorStop(0,'#1c0734');bg.addColorStop(.55,'#0d031b');bg.addColorStop(1,'#030008');
    ctx.fillStyle=bg;ctx.fillRect(0,0,w,h);
    for(const s of stars){
      const twinkle=.45+.55*Math.sin(t*s.speed*3+s.p);
      glowDot(s.x,s.y,s.r,'#e9d5ff',s.a*twinkle*.8);
    }
    const cx=w/2, cy=h/2+Math.min(20,h*.025);
    // Anillos de galaxia
    ctx.save();ctx.translate(cx,cy);ctx.rotate(-.18);
    for(let ring=0;ring<4;ring++){
      ctx.beginPath();ctx.ellipse(0,0,Math.min(w,h)*(.19+ring*.065),Math.min(w,h)*(.055+ring*.018),0,0,Math.PI*2);
      ctx.strokeStyle=`rgba(168,85,247,${.12-ring*.02})`;ctx.lineWidth=1;ctx.stroke();
    }
    ctx.restore();
    for(const p of dust){
      p.a += p.s;
      const x=cx+Math.cos(p.a+t*.13)*p.r;
      const y=cy+Math.sin(p.a+t*.13)*p.r*.48;
      glowDot(x,y,p.size,Math.random()>.45?'#c084fc':'#f5d0fe',.55);
    }
    // Flor morada de partículas
    const scale=Math.min(w,h)*.001;
    for(const p of flower){
      const pulse=1+.025*Math.sin(t*2+p.phase);
      const radius=p.r*pulse;
      const x=cx+Math.cos(p.a)*radius;
      const y=cy+Math.sin(p.a)*radius;
      const col=p.color>.8?'#fff0ff':p.color>.45?'#d8b4fe':'#a855f7';
      glowDot(x,y,p.size,col,.55+.4*Math.sin(t*2+p.phase)**2);
    }
    // Centro luminoso
    const core=ctx.createRadialGradient(cx,cy,1,cx,cy,Math.min(w,h)*.075);
    core.addColorStop(0,'rgba(255,240,255,.9)');core.addColorStop(.25,'rgba(216,180,254,.34)');core.addColorStop(1,'rgba(168,85,247,0)');
    ctx.fillStyle=core;ctx.beginPath();ctx.arc(cx,cy,Math.min(w,h)*.075,0,Math.PI*2);ctx.fill();
    glowDot(cx,cy,3,'#fff7ff',.95);
    requestAnimationFrame(draw);
  }
  window.addEventListener('resize',resize);
  resize();draw();
  const overlay=document.getElementById('overlay');
  document.getElementById('letterBtn').addEventListener('click',()=>overlay.classList.add('show'));
  document.getElementById('close').addEventListener('click',()=>overlay.classList.remove('show'));
  overlay.addEventListener('click',e=>{if(e.target===overlay)overlay.classList.remove('show')});
  window.addEventListener('keydown',e=>{if(e.key==='Escape')overlay.classList.remove('show')});
})();
</script>
</body>
</html>

7,033 chars · codepastes.com