<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Para Giovanna 💖</title>
<style>
:root{
--bg1:#0b0612;
--bg2:#160822;
--pink:#ff4fd8;
--rose:#ff2d6f;
--peach:#ffb3c7;
--violet:#8a2be2;
--gold:#ffd1a6;
--text:#fff7fb;
--muted:rgba(255,255,255,.72);
--glass:rgba(255,255,255,.10);
--glass2:rgba(255,255,255,.07);
--stroke:rgba(255,255,255,.18);
--shadow: 0 18px 60px rgba(0,0,0,.45);
--radius: 22px;
}
/* Reset básico (amigável pra embed) */
.love-wrap, .love-wrap *{ box-sizing:border-box; }
.love-wrap{
position: relative;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji";
color: var(--text);
overflow: hidden;
border-radius: 18px;
isolation: isolate;
min-height: 100vh;
}
/* Fundo com gradientes irradiantes */
.love-bg{
position:absolute; inset:0;
background:
radial-gradient(1200px 600px at 15% 15%, rgba(255,79,216,.35), transparent 65%),
radial-gradient(900px 520px at 85% 20%, rgba(138,43,226,.28), transparent 62%),
radial-gradient(900px 600px at 50% 85%, rgba(255,45,111,.25), transparent 66%),
linear-gradient(180deg, var(--bg1), var(--bg2) 55%, #0b0612);
filter: saturate(1.15) contrast(1.05);
transform: translateZ(0);
}
/* “Auroras” suaves que se movem */
.aurora{
position:absolute; inset:-20%;
background:
radial-gradient(closest-side at 30% 40%, rgba(255,79,216,.22), transparent 60%),
radial-gradient(closest-side at 70% 35%, rgba(255,45,111,.20), transparent 58%),
radial-gradient(closest-side at 52% 70%, rgba(255,209,166,.14), transparent 62%),
radial-gradient(closest-side at 80% 80%, rgba(138,43,226,.16), transparent 65%);
animation: drift 16s ease-in-out infinite alternate;
opacity: .9;
mix-blend-mode: screen;
pointer-events:none;
will-change: transform;
}
@keyframes drift{
from { transform: translate3d(-2%, -1%, 0) scale(1.02); }
to { transform: translate3d( 2%, 1%, 0) scale(1.05); }
}
/* Ruído sutil (sem imagem) */
.grain{
position:absolute; inset:0;
opacity:.10;
background-image:
repeating-linear-gradient(0deg, rgba(255,255,255,.06) 0 1px, transparent 1px 2px),
repeating-linear-gradient(90deg, rgba(255,255,255,.04) 0 1px, transparent 1px 3px);
mix-blend-mode: overlay;
pointer-events:none;
}
/* Container */
.love-container{
position:relative;
max-width: 980px;
margin: 0 auto;
padding: 56px 18px 80px;
z-index: 2;
}
/* Topo */
.hero{
position:relative;
border: 1px solid var(--stroke);
background: linear-gradient(180deg, var(--glass), var(--glass2));
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 34px 20px 22px;
overflow:hidden;
}
.hero::before{
content:"";
position:absolute;
inset:-2px;
background: radial-gradient(600px 240px at 20% 20%, rgba(255,79,216,.35), transparent 60%),
radial-gradient(520px 240px at 80% 0%, rgba(138,43,226,.30), transparent 60%);
opacity:.85;
filter: blur(0.2px);
pointer-events:none;
}
.badge{
display:inline-flex;
gap:10px;
align-items:center;
padding: 10px 14px;
border-radius: 999px;
border: 1px solid rgba(255,255,255,.22);
background: rgba(0,0,0,.18);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
font-size: 13px;
letter-spacing: .25px;
color: rgba(255,255,255,.85);
position:relative;
z-index:1;
}
.badge .dot{
width: 9px; height: 9px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #fff, var(--pink) 40%, rgba(255,79,216,.05) 70%);
box-shadow: 0 0 16px rgba(255,79,216,.8);
}
.hero h1{
margin: 14px 0 10px;
font-weight: 800;
line-height: 1.05;
font-size: clamp(30px, 4.2vw, 52px);
letter-spacing: -0.03em;
position:relative;
z-index:1;
}
.glow-text{
background: linear-gradient(90deg, #fff, var(--peach), #fff);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 0 28px rgba(255,179,199,.25);
}
.hero p{
margin: 0 0 18px;
max-width: 64ch;
color: var(--muted);
font-size: 16px;
line-height: 1.6;
position:relative;
z-index:1;
}
.cta-row{
display:flex;
flex-wrap: wrap;
gap: 12px;
align-items:center;
position:relative;
z-index:1;
margin-top: 10px;
}
.btn{
appearance:none;
border: 1px solid rgba(255,255,255,.22);
background: rgba(0,0,0,.18);
color: white;
padding: 12px 14px;
border-radius: 14px;
cursor:pointer;
transition: transform .15s ease, box-shadow .2s ease, background .2s ease;
display:inline-flex;
gap:10px;
align-items:center;
font-weight: 650;
letter-spacing: .2px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
user-select:none;
}
.btn:hover{ transform: translateY(-1px); box-shadow: 0 14px 34px rgba(0,0,0,.30); }
.btn:active{ transform: translateY(0px) scale(.99); }
.btn-primary{
border-color: rgba(255,79,216,.45);
background: linear-gradient(180deg, rgba(255,79,216,.28), rgba(255,45,111,.16));
box-shadow: 0 18px 60px rgba(255,45,111,.10);
}
.btn-primary .icon{
filter: drop-shadow(0 0 18px rgba(255,79,216,.7));
}
.subnote{
font-size: 13px;
color: rgba(255,255,255,.70);
opacity: .95;
}
/* Seções */
.grid{
margin-top: 18px;
display:grid;
grid-template-columns: 1.2fr .8fr;
gap: 14px;
}
@media (max-width: 860px){
.grid{ grid-template-columns: 1fr; }
}
.card{
position:relative;
border: 1px solid rgba(255,255,255,.16);
background: linear-gradient(180deg, rgba(255,255,255,.09), rgba(255,255,255,.04));
border-radius: var(--radius);
box-shadow: 0 18px 60px rgba(0,0,0,.32);
overflow:hidden;
padding: 18px;
}
.card h2{
margin: 0 0 8px;
font-size: 18px;
letter-spacing: -.01em;
}
.card p{
margin: 0;
color: rgba(255,255,255,.78);
line-height: 1.65;
font-size: 15px;
}
.timeline{
margin-top: 8px;
display:grid;
gap: 10px;
}
.t-item{
display:flex;
gap: 12px;
align-items:flex-start;
padding: 12px;
border-radius: 16px;
border: 1px solid rgba(255,255,255,.12);
background: rgba(0,0,0,.12);
}
.t-dot{
width: 10px; height: 10px;
border-radius: 50%;
margin-top: 6px;
background: radial-gradient(circle at 30% 30%, #fff, var(--rose) 42%, rgba(255,45,111,.08) 70%);
box-shadow: 0 0 18px rgba(255,45,111,.7);
flex: 0 0 auto;
}
.t-title{
font-weight: 750;
letter-spacing: .15px;
margin: 0 0 4px;
}
.t-desc{
margin: 0;
font-size: 14px;
color: rgba(255,255,255,.74);
line-height: 1.55;
}
.quote{
margin-top: 14px;
padding: 16px;
border-radius: 18px;
border: 1px dashed rgba(255,255,255,.25);
background: rgba(0,0,0,.10);
position:relative;
overflow:hidden;
}
.quote::before{
content:"“";
position:absolute;
left: 12px;
top: -10px;
font-size: 64px;
opacity:.22;
color: rgba(255,255,255,.85);
pointer-events:none;
}
.quote p{
margin: 0;
padding-left: 18px;
color: rgba(255,255,255,.82);
font-size: 15px;
line-height: 1.7;
}
/* Galeria de “pílulas” */
.pills{
display:flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 12px;
}
.pill{
padding: 10px 12px;
border-radius: 999px;
border: 1px solid rgba(255,255,255,.16);
background: rgba(0,0,0,.12);
color: rgba(255,255,255,.82);
font-size: 13px;
letter-spacing:.2px;
transition: transform .16s ease, box-shadow .2s ease, border-color .2s ease;
}
.pill:hover{
transform: translateY(-2px);
border-color: rgba(255,79,216,.35);
box-shadow: 0 18px 50px rgba(255,45,111,.10);
}
/* Seção surpresa */
.surprise{
margin-top: 14px;
display:grid;
gap: 12px;
}
.love-letter{
position:relative;
padding: 18px;
border-radius: var(--radius);
border: 1px solid rgba(255,255,255,.16);
background: linear-gradient(180deg, rgba(255,79,216,.16), rgba(0,0,0,.12));
overflow:hidden;
}
.love-letter h3{
margin: 0 0 8px;
font-size: 16px;
letter-spacing: -.01em;
}
.love-letter .msg{
margin: 0;
color: rgba(255,255,255,.86);
line-height: 1.75;
font-size: 15px;
min-height: 5.2em;
}
/* Reveal on scroll */
.reveal{
opacity: 0;
transform: translateY(14px) scale(.99);
filter: blur(4px);
transition: opacity .7s ease, transform .7s ease, filter .8s ease;
will-change: transform, opacity, filter;
}
.reveal.is-visible{
opacity: 1;
transform: translateY(0) scale(1);
filter: blur(0);
}
/* Floating elements layer */
.float-layer{
position:absolute; inset:0;
pointer-events:none;
z-index: 1;
overflow:hidden;
}
.floaty{
position:absolute;
left: var(--x);
top: var(--y);
width: var(--s);
height: var(--s);
opacity: var(--o);
transform: translate3d(0,0,0);
filter: drop-shadow(0 0 18px rgba(255,79,216,.22));
animation: floatUp var(--d) linear infinite;
will-change: transform;
}
@keyframes floatUp{
0% { transform: translate3d(0, 0, 0) rotate(0deg); }
100% { transform: translate3d(0, -130vh, 0) rotate(260deg); }
}
/* Coração em CSS */
.heart{
position:relative;
width: 100%;
height: 100%;
transform: rotate(45deg);
background: radial-gradient(circle at 30% 30%, rgba(255,255,255,.8), rgba(255,79,216,.25) 25%, rgba(255,45,111,.55) 62%, rgba(255,45,111,.20) 100%);
border-radius: 10px;
}
.heart::before,
.heart::after{
content:"";
position:absolute;
width: 100%;
height: 100%;
background: inherit;
border-radius: 50%;
}
.heart::before{ left:-50%; top:0; }
.heart::after{ left:0; top:-50%; }
/* Partículas “bokeh” */
.bokeh{
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, rgba(255,255,255,.45), rgba(255,179,199,.22) 35%, rgba(255,45,111,.14) 70%, transparent 72%);
box-shadow: 0 0 24px rgba(255,79,216,.18);
}
/* Rodapé */
.footer{
margin-top: 16px;
padding: 16px;
border-radius: var(--radius);
border: 1px solid rgba(255,255,255,.14);
background: rgba(0,0,0,.12);
text-align:center;
color: rgba(255,255,255,.72);
font-size: 13px;
}
/* Parallax sutil: aplicado via JS em translateY */
.parallax{
will-change: transform;
}
/* Acessibilidade: reduz movimento */
@media (prefers-reduced-motion: reduce){
.aurora, .floaty, .reveal{ animation: none !important; transition: none !important; }
}
</style>
</head>
<body style="margin:0;">
<div class="love-wrap" id="loveApp">
<div class="love-bg parallax" data-depth="0.20"></div>
<div class="aurora parallax" data-depth="0.35"></div>
<div class="grain"></div>
<!-- Elementos flutuantes -->
<div class="float-layer" id="floatLayer" aria-hidden="true"></div>
<div class="love-container">
<header class="hero reveal">
<div class="badge">
<span class="dot"></span>
<span>Um cantinho feito com amor • Para <strong>Giovanna</strong> 💖</span>
</div>
<h1>
Giovanna, <span class="glow-text">você é meu lugar favorito</span>.
</h1>
<p>
Eu quis transformar sentimento em experiência: luz suave, movimento delicado e palavras que lembram
o que eu já sei — <strong>você é a melhor parte dos meus dias</strong>.
</p>
<div class="cta-row">
<button class="btn btn-primary" id="btnSurpresa" type="button">
<span class="icon">✨</span>
<span>Abrir uma surpresa</span>
</button>
<button class="btn" id="btnConfete" type="button">
<span class="icon">💗</span>
<span>Espalhar corações</span>
</button>
<span class="subnote">Role a página — tem magia em cada seção.</span>
</div>
</header>
<section class="grid">
<article class="card reveal">
<h2>Três coisas que eu amo em você</h2>
<div class="timeline">
<div class="t-item">
<div class="t-dot"></div>
<div>
<div class="t-title">Seu jeito de acolher</div>
<p class="t-desc">Você faz o mundo parecer mais leve só por existir nele.</p>
</div>
</div>
<div class="t-item">
<div class="t-dot"></div>
<div>
<div class="t-title">Sua força gentil</div>
<p class="t-desc">Você é firme quando precisa — e doce em todos os outros momentos.</p>
</div>
</div>
<div class="t-item">
<div class="t-dot"></div>
<div>
<div class="t-title">A nossa parceria</div>
<p class="t-desc">Eu te escolho, de novo, todos os dias. E é sempre a melhor escolha.</p>
</div>
</div>
</div>
<div class="quote">
<p id="quoteText">
“Se eu pudesse, colocaria um ‘eu te amo’ em cada detalhe do seu dia.”
</p>
</div>
<div class="pills" aria-label="pequenas promessas">
<span class="pill">Cuidar de nós</span>
<span class="pill">Te ouvir com calma</span>
<span class="pill">Te admirar sempre</span>
<span class="pill">Rir contigo</span>
<span class="pill">Ser teu lar</span>
</div>
</article>
<aside class="card reveal">
<h2>Um bilhete que muda</h2>
<p>
Cada clique traz uma frase nova — como eu lembrando você (de novo) do quanto é amada.
</p>
<div class="surprise">
<div class="love-letter">
<h3>Mensagem para a Giovanna 💌</h3>
<p class="msg" id="dynamicMsg"></p>
</div>
<button class="btn btn-primary" id="btnNovaMsg" type="button">
<span class="icon">🔁</span>
<span>Nova mensagem</span>
</button>
<button class="btn" id="btnCopiar" type="button">
<span class="icon">📋</span>
<span>Copiar mensagem</span>
</button>
</div>
</aside>
</section>
<section class="card reveal" style="margin-top:14px;">
<h2>Quando você rola… o sentimento acompanha</h2>
<p>
Esse efeito é simples, mas simbólico: <strong>eu caminho com você</strong>.
Onde você vai, eu quero ir também — com respeito, carinho e presença.
</p>
<div class="grid" style="margin-top:14px;">
<div class="card reveal" style="background: rgba(0,0,0,.10);">
<h2>Pequeno manifesto</h2>
<p>
Giovanna, eu amo a sua essência. Amo seus detalhes. Amo sua história.
E eu sou feliz por poder somar na sua vida — todos os dias.
</p>
</div>
<div class="card reveal" style="background: rgba(0,0,0,.10);">
<h2>Assinado</h2>
<p>
Com amor, paciência, desejo de futuro — e uma vontade enorme de te fazer sorrir.
<br><br>
<strong>Eu te amo, Giovanna.</strong> 💖
</p>
</div>
</div>
</section>
<footer class="footer reveal">
Feito com carinho em HTML + CSS + JS • Um site simples, mas com sentimento infinito.
</footer>
</div>
</div>
<script>
(function(){
const app = document.getElementById('loveApp');
const floatLayer = document.getElementById('floatLayer');
const dynamicMsg = document.getElementById('dynamicMsg');
const quoteText = document.getElementById('quoteText');
const mensagens = [
"Giovanna, você é a minha paz em forma de pessoa. Obrigado por ser minha casa.",
"Eu amo o jeito como você ilumina até os dias comuns — com você, tudo fica especial.",
"Se eu pudesse te dar um presente eterno, seria a certeza de que você é muito amada.",
"Você é meu sonho que virou realidade. E eu ainda me pego sorrindo por isso.",
"Giovanna, eu te admiro: pelo que você é, pelo que constrói, pelo que inspira.",
"Meu lugar favorito é onde sua mão encontra a minha. Sempre.",
"Eu prometo: cuidado, respeito, carinho e presença. Todo dia. De verdade.",
"Você é a melhor notícia do meu mundo — e a minha escolha mais bonita.",
"Obrigado por me ensinar amor com delicadeza e coragem. Eu te amo demais.",
"Eu te amo no detalhe: no seu sorriso, na sua voz, no seu jeito de olhar."
];
const quotes = [
"“Amar você é a forma mais bonita que eu encontrei de viver.”",
"“Seu nome combina com a palavra ‘sorte’.”",
"“Eu escolheria você em todas as versões do universo.”",
"“Com você, o futuro parece gentil.”",
"“O meu coração reconhece o seu.”"
];
function pickRandom(arr){
return arr[Math.floor(Math.random() * arr.length)];
}
function typeWriter(el, text, speed=18){
el.textContent = "";
let i = 0;
const timer = setInterval(() => {
el.textContent += text.charAt(i);
i++;
if(i >= text.length) clearInterval(timer);
}, speed);
}
function novaMensagem(){
const msg = pickRandom(mensagens);
typeWriter(dynamicMsg, msg, 16);
quoteText.textContent = pickRandom(quotes);
}
// Reveal on scroll
const io = new IntersectionObserver((entries) => {
for(const e of entries){
if(e.isIntersecting) e.target.classList.add('is-visible');
}
}, { threshold: 0.14 });
document.querySelectorAll('.reveal').forEach(el => io.observe(el));
// Parallax scroll
function parallax(){
const y = window.scrollY || document.documentElement.scrollTop || 0;
document.querySelectorAll('.parallax').forEach(el => {
const depth = parseFloat(el.getAttribute('data-depth') || "0.2");
el.style.transform = `translate3d(0, ${y * depth * -0.15}px, 0)`;
});
}
window.addEventListener('scroll', parallax, { passive:true });
parallax();
// Floating elements generator
function createFloaty(kind){
const el = document.createElement('div');
el.className = 'floaty';
const size = (Math.random() * 26 + 10).toFixed(0) + 'px';
const x = (Math.random() * 100).toFixed(2) + '%';
const y = (Math.random() * 110 + 95).toFixed(2) + '%'; // começa abaixo
const o = (Math.random() * 0.35 + 0.10).toFixed(2);
const d = (Math.random() * 10 + 10).toFixed(2) + 's';
el.style.setProperty('--s', size);
el.style.setProperty('--x', x);
el.style.setProperty('--y', y);
el.style.setProperty('--o', o);
el.style.setProperty('--d', d);
const inner = document.createElement('div');
if(kind === 'heart'){
inner.className = 'heart';
}else{
inner.className = 'bokeh';
inner.style.width = "100%";
inner.style.height = "100%";
}
el.appendChild(inner);
floatLayer.appendChild(el);
// remove depois da animação
const ms = parseFloat(d) * 1000;
setTimeout(() => el.remove(), ms + 200);
}
function seedFloaties(){
// seed inicial: alguns corações e bokehs
for(let i=0;i<12;i++) createFloaty(i%3===0 ? 'heart' : 'bokeh');
// loop contínuo, leve
setInterval(() => createFloaty(Math.random() < 0.40 ? 'heart' : 'bokeh'), 900);
}
// “Confete” de corações
function burstHearts(amount=18){
for(let i=0;i<amount;i++){
setTimeout(() => createFloaty('heart'), i * 40);
}
}
// Botões
document.getElementById('btnNovaMsg').addEventListener('click', () => {
novaMensagem();
burstHearts(10);
});
document.getElementById('btnSurpresa').addEventListener('click', () => {
// scroll suave até a área da carta
const target = document.querySelector('.love-letter');
if(target){
target.scrollIntoView({ behavior:'smooth', block:'center' });
}
burstHearts(16);
});
document.getElementById('btnConfete').addEventListener('click', () => {
burstHearts(28);
});
document.getElementById('btnCopiar').addEventListener('click', async () => {
const text = dynamicMsg.textContent.trim();
try{
await navigator.clipboard.writeText(text);
quoteText.textContent = "“Copiado. Agora é só colar e fazer ela sorrir.” 💖";
burstHearts(8);
}catch(err){
// fallback simples
const ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.left = '-9999px';
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
ta.remove();
quoteText.textContent = "“Copiado (modo compatível). Você é romântico e eficiente 😄”";
burstHearts(8);
}
});
// Inicialização
novaMensagem();
seedFloaties();
// Pequeno “brilho” reagindo ao mouse (bem sutil)
let raf = null;
app.addEventListener('mousemove', (e) => {
if(raf) return;
raf = requestAnimationFrame(() => {
const r = app.getBoundingClientRect();
const x = ((e.clientX - r.left) / r.width) * 100;
const y = ((e.clientY - r.top) / r.height) * 100;
app.style.setProperty('--mx', x + '%');
app.style.setProperty('--my', y + '%');
// brilho dinâmico discreto no fundo
const bg = app.querySelector('.love-bg');
if(bg){
bg.style.filter = `saturate(1.2) contrast(1.05) brightness(1.02)`;
}
raf = null;
});
});
})();
</script>
</body>
</html>