<!
doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Capa — Morri jogando RPG e reencarnei como um NPC da história</title>
<!-- Fonts -->
<link rel="preconnect" href="[Link]
<link rel="preconnect" href="[Link] crossorigin>
<link href="[Link]
family=Unbounded:wght@500;700;800&family=Manrope:wght@300;400;600;700&display=swap"
rel="stylesheet">
<style>
:root{
--bg0:#07060a;
--bg1:#0b0711;
--ink:#f7f4ff;
--muted:rgba(247,244,255,.72);
--hot:#ff2d55;
--ember:#ff4d2d;
--violet:#8b5cf6;
--aqua:#39ffd7;
--glass:rgba(255,255,255,.08);
--stroke:rgba(255,255,255,.16);
--shadow: 0 28px 90px rgba(0,0,0,.62);
--shadow2: 0 18px 65px rgba(0,0,0,.55);
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
font-family: "Manrope", system-ui, -apple-system, Segoe UI, Roboto, sans-
serif;
color:var(--ink);
background:
radial-gradient(1200px 900px at 18% 12%, rgba(255,45,85,.18), transparent
60%),
radial-gradient(1000px 800px at 84% 25%, rgba(139,92,246,.18), transparent
60%),
radial-gradient(900px 700px at 52% 86%, rgba(57,255,215,.10), transparent
62%),
linear-gradient(180deg, var(--bg0), var(--bg1));
overflow-x:hidden;
}
/* grain */
body::before{
content:"";
position:fixed; inset:0;
pointer-events:none;
opacity:.22;
mix-blend-mode:overlay;
background-image:url("data:image/svg+xml,%3Csvg
xmlns='[Link] width='240' height='240'%3E%3Cfilter id='n'%3E
%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'
stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240'
filter='url(%23n)' opacity='.22'/%3E%3C/svg%3E");
}
.page{
min-height:100%;
display:grid;
place-items:center;
padding:clamp(16px, 3vw, 34px);
}
.cover{
width:min(780px, 100%);
aspect-ratio: 2 / 3;
position:relative;
border-radius:28px;
overflow:hidden;
box-shadow:var(--shadow);
border:1px solid rgba(255,255,255,.12);
background:
radial-gradient(900px 700px at 20% 18%, rgba(255,45,85,.26), transparent
62%),
radial-gradient(900px 700px at 84% 22%, rgba(139,92,246,.18), transparent
62%),
radial-gradient(900px 700px at 50% 88%, rgba(255,77,45,.16), transparent
60%),
linear-gradient(180deg, rgba(12,10,18,.95), rgba(6,6,10,.97));
isolation:isolate;
}
.cover::after{
content:"";
position:absolute; inset:14px;
border-radius:22px;
border:1px solid rgba(255,255,255,.14);
box-shadow: 0 0 0 1px rgba(0,0,0,.35) inset;
pointer-events:none;
z-index:10;
}
/* diagonal energy */
.energy{
position:absolute;
inset:-40%;
transform:rotate(-10deg);
background:
linear-gradient(115deg,
transparent 0 42%,
rgba(255,45,85,.16) 42% 45%,
transparent 45% 53%,
rgba(139,92,246,.12) 53% 56%,
transparent 56% 100%);
opacity:.9;
z-index:0;
}
/* ===== Title ===== */
.title{
position:absolute;
left:clamp(18px, 4vw, 34px);
right:clamp(18px, 4vw, 34px);
top:clamp(18px, 4vw, 34px);
z-index:9;
}
.badge{
display:inline-flex;
align-items:center;
gap:10px;
padding:10px 12px;
border-radius:999px;
background:linear-gradient(180deg, rgba(255,255,255,.10),
rgba(255,255,255,.05));
border:1px solid rgba(255,255,255,.14);
backdrop-filter: blur(10px);
box-shadow: 0 14px 40px rgba(0,0,0,.35);
color:rgba(247,244,255,.78);
font-size:clamp(12px, 2.2vw, 13px);
width:max-content;
}
.badge i{
width:10px;height:10px;border-radius:50%;
background: radial-gradient(circle at 30% 30%, #fff, rgba(255,255,255,.25)
30%, rgba(255,45,85,1) 60%, rgba(255,45,85,.1) 100%);
box-shadow: 0 0 0 4px rgba(255,45,85,.16), 0 0 22px rgba(255,45,85,.45);
display:inline-block;
}
h1{
margin:14px 0 0;
font-family:"Unbounded", system-ui, sans-serif;
font-weight:800;
letter-spacing:-0.02em;
line-height:1.05;
font-size:clamp(22px, 4.2vw, 44px);
text-wrap:balance;
text-shadow: 0 16px 44px rgba(0,0,0,.6);
}
h1 .grad{
background: linear-gradient(90deg, rgba(255,45,85,1), rgba(255,77,45,1),
rgba(139,92,246,1));
-webkit-background-clip:text;
background-clip:text;
color:transparent;
}
.subtitle{
margin-top:10px;
max-width:62ch;
color:rgba(247,244,255,.72);
line-height:1.45;
font-size:clamp(12px, 2.2vw, 14px);
}
/* ===== Background last photo: huge, behind, "holding the dice" ===== */
.bgWrap{
position:absolute;
inset:0;
z-index:1;
pointer-events:none;
}
.bgWrap .vignette{
position:absolute; inset:-10%;
background:
radial-gradient(900px 700px at 60% 35%, rgba(255,45,85,.20), transparent
62%),
radial-gradient(900px 700px at 40% 55%, rgba(139,92,246,.14), transparent
64%),
radial-gradient(900px 700px at 52% 84%, rgba(57,255,215,.09), transparent
65%),
linear-gradient(180deg, rgba(0,0,0,.05), rgba(0,0,0,.45));
filter: blur(10px);
opacity:.95;
transform: translateY(4%);
}
.bgWrap .bgLast{
position:absolute;
inset:-8% -12% -8% -12%;
opacity:.44;
mix-blend-mode: screen;
filter: saturate(1.08) contrast(1.05);
background: none;
background-size: cover;
background-position:center;
background-repeat:no-repeat;
}
.bgWrap .shade{
position:absolute; inset:0;
background:
radial-gradient(900px 800px at 50% 25%, rgba(0,0,0,.25), rgba(0,0,0,.0)
55%),
linear-gradient(180deg, rgba(0,0,0,.15), rgba(0,0,0,.55));
opacity:.9;
}
/* ===== Dice (use your anime-style pink D20) ===== */
.dice{
position:absolute;
right:-16%;
bottom:-14%;
width:min(92%, 780px);
aspect-ratio:1/1;
z-index:2;
transform: rotate(-10deg);
filter: drop-shadow(0 38px 95px rgba(0,0,0,.68));
pointer-events:none;
}
.dice .img{
width:100%; height:100%;
border-radius:26px;
background: none;
background-size:contain;
background-position:center;
background-repeat:no-repeat;
opacity:.92;
}
.dice .glow{
position:absolute; inset:-30%;
background:
radial-gradient(closest-side at 62% 50%, rgba(255,45,85,.35), transparent
70%),
radial-gradient(closest-side at 40% 55%, rgba(139,92,246,.22), transparent
72%),
radial-gradient(closest-side at 55% 70%, rgba(57,255,215,.12), transparent
74%);
filter: blur(16px);
opacity:.9;
z-index:-1;
}
/* ===== Foreground composition =====
- First photo (frame)
- Second photo inside first
- Third photo holding first (behind it a bit)
*/
.scene{
position:absolute;
left:clamp(16px, 3.8vw, 34px);
right:clamp(16px, 3.8vw, 34px);
bottom:clamp(16px, 3.8vw, 34px);
height:52%;
z-index:8;
display:grid;
grid-template-columns: 1.05fr .95fr;
gap:clamp(12px, 2.2vw, 18px);
align-items:end;
}
/* Third photo (holder) on the right */
.holder{
position:relative;
height:100%;
display:grid;
align-items:end;
justify-items:end;
}
.holderCard{
width:100%;
height:100%;
border-radius:24px;
overflow:hidden;
border:1px solid rgba(255,255,255,.14);
background:linear-gradient(180deg, rgba(255,255,255,.10),
rgba(255,255,255,.05));
backdrop-filter: blur(10px);
box-shadow: var(--shadow2);
position:relative;
transform: rotate(2deg);
}
.holderImg{
position:absolute; inset:0;
background-size:cover;
background-position:center;
background-repeat:no-repeat;
filter:saturate(1.06) contrast(1.06);
}
.holderCard::before{
content:"";
position:absolute; inset:0;
background:
radial-gradient(600px 420px at 70% 30%, rgba(255,45,85,.15), transparent
60%),
radial-gradient(600px 420px at 35% 70%, rgba(139,92,246,.12), transparent
62%),
linear-gradient(180deg, rgba(0,0,0,.10), rgba(0,0,0,.35));
mix-blend-mode:overlay;
pointer-events:none;
}
/* Arm overlay to sell "holding" */
.arm{
position:absolute;
left:-12%;
bottom:-10%;
width:126%;
height:54%;
pointer-events:none;
opacity:.92;
filter: drop-shadow(0 18px 40px rgba(0,0,0,.55));
}
/* First photo frame on the left */
.frame{
position:relative;
height:100%;
display:grid;
align-items:end;
}
.frameCard{
width:100%;
height:100%;
border-radius:24px;
overflow:hidden;
border:1px solid rgba(255,255,255,.16);
background:linear-gradient(180deg, rgba(255,255,255,.10),
rgba(255,255,255,.05));
backdrop-filter: blur(10px);
box-shadow: var(--shadow2);
position:relative;
transform: rotate(-1.4deg);
}
.frameImg{
position:absolute; inset:0;
background-size:cover;
background-position:center;
background-repeat:no-repeat;
filter:saturate(1.06) contrast(1.08);
}
/* Second photo inside first */
.inner{
position:absolute;
inset:clamp(14px, 2.2vw, 18px);
border-radius:18px;
overflow:hidden;
border:1px solid rgba(255,255,255,.18);
box-shadow: 0 0 0 1px rgba(0,0,0,.35) inset;
background: linear-gradient(180deg, rgba(255,255,255,.08),
rgba(255,255,255,.03));
}
.inner::before{
content:"";
position:absolute; inset:-40px;
background:
radial-gradient(closest-side at 25% 35%, rgba(255,45,85,.22), transparent
70%),
radial-gradient(closest-side at 70% 30%, rgba(139,92,246,.16), transparent
72%),
radial-gradient(closest-side at 55% 80%, rgba(57,255,215,.10), transparent
74%);
filter: blur(14px);
opacity:.9;
}
.innerImg{
position:absolute; inset:0;
background-size:cover;
background-position:center;
background-repeat:no-repeat;
filter:saturate(1.06) contrast(1.06);
}
/* Make it look like holder is holding frame */
.frameCard{
z-index:2;
}
.holderCard{
z-index:1;
}
.frameCard{
margin-right:-10%;
}
/* small label */
.chip{
position:absolute;
left:14px; top:14px;
z-index:5;
padding:8px 10px;
border-radius:999px;
background:rgba(0,0,0,.45);
border:1px solid rgba(255,255,255,.18);
color:rgba(247,244,255,.84);
font-size:12px;
letter-spacing:.02em;
backdrop-filter: blur(8px);
}
/* Reveal animation */
.reveal{
opacity:0;
transform: translateY(14px);
animation: in .9s cubic-bezier(.2,.9,.2,1) forwards;
}
.d1{animation-delay:.08s}
.d2{animation-delay:.18s}
.d3{animation-delay:.28s}
.d4{animation-delay:.38s}
@keyframes in{to{opacity:1; transform: translateY(0)}}
/* Controls */
.controls{
width:min(780px, 100%);
display:flex;
gap:10px;
flex-wrap:wrap;
justify-content:space-between;
align-items:center;
margin-top:14px;
color:rgba(247,244,255,.66);
font-size:12px;
}
.ctlGroup{display:flex; gap:10px; flex-wrap:wrap; align-items:center}
.file{
display:inline-flex;
align-items:center;
gap:10px;
padding:10px 12px;
border-radius:999px;
border:1px dashed rgba(255,255,255,.22);
background:rgba(0,0,0,.18);
backdrop-filter: blur(8px);
cursor:pointer;
user-select:none;
}
input[type="file"]{display:none}
.btn{
appearance:none;
border:1px solid rgba(255,255,255,.16);
background:linear-gradient(180deg, rgba(255,255,255,.10),
rgba(255,255,255,.05));
color:rgba(247,244,255,.86);
padding:10px 12px;
border-radius:999px;
cursor:pointer;
font-weight:800;
letter-spacing:.01em;
transition: transform .15s ease, border-color .2s ease, box-shadow .2s ease;
backdrop-filter: blur(10px);
box-shadow: 0 14px 40px rgba(0,0,0,.25);
font-size:12px;
}
.btn:hover{
transform: translateY(-2px);
border-color: rgba(255,45,85,.35);
box-shadow: 0 18px 55px rgba(0,0,0,.35), 0 0 0 6px rgba(255,45,85,.10);
}
.btn:active{transform: translateY(0)}
/* Mobile */
@media (max-width: 640px){
.scene{
grid-template-columns: 1fr;
height:58%;
}
.holder{
height:72%;
}
.frameCard{margin-right:0}
.dice{
right:-44%;
bottom:-28%;
opacity:.78;
}
}
</style>
</head>
<body>
<div class="page">
<main class="cover" role="img" aria-label="Capa de webnovel anime-style com
composição de imagens e título.">
<div class="energy" aria-hidden="true"></div>
<!-- BACKGROUND: última foto grande -->
<div class="bgWrap" aria-hidden="true">
<div class="vignette"></div>
<div class="bgLast" id="bgLast"></div>
<div class="shade"></div>
</div>
<!-- DADO (anime-style) enorme -->
<div class="dice" aria-hidden="true">
<div class="glow"></div>
<div class="img" id="diceImg"></div>
</div>
<!-- TITLE -->
<section class="title reveal d1">
<div class="badge"><i aria-hidden="true"></i> Webnovel • Isekai • RPG •
NPC</div>
<h1>
<span class="grad">Morri jogando RPG</span> e reencarnei como um NPC da
história
</h1>
<p class="subtitle">
Composição: a 2ª imagem dentro da 1ª; a 3ª “segura” a 1ª; a última fica
ao fundo, enorme, atrás, segurando o dado.
</p>
</section>
<!-- FOREGROUND SCENE -->
<section class="scene reveal d2" aria-label="Composição principal da capa">
<!-- LEFT: first photo with second inside -->
<div class="frame">
<article class="frameCard" aria-label="Primeira foto com segunda dentro">
<div class="chip">1ª foto (moldura) + 2ª (dentro)</div>
<div class="frameImg" id="firstImg"></div>
<div class="inner" aria-label="Segunda foto dentro da primeira">
<div class="innerImg" id="secondImg"></div>
</div>
</article>
</div>
<!-- RIGHT: third photo holding -->
<aside class="holder" aria-label="Terceira foto segurando a primeira">
<article class="holderCard">
<div class="chip">3ª foto (segurando)</div>
<div class="holderImg" id="thirdImg"></div>
<!-- Arm overlay -->
<svg class="arm" viewBox="0 0 1200 600" preserveAspectRatio="none"
aria-hidden="true">
<defs>
<linearGradient id="armG" x1="0" x2="1">
<stop offset="0" stop-color="rgba(0,0,0,.0)"/>
<stop offset=".32" stop-color="rgba(0,0,0,.30)"/>
<stop offset="1" stop-color="rgba(0,0,0,.0)"/>
</linearGradient>
<linearGradient id="skin" x1="0" x2="1">
<stop offset="0" stop-color="rgba(247,213,198,.78)"/>
<stop offset="1" stop-color="rgba(206,167,167,.78)"/>
</linearGradient>
</defs>
<path d="M40 420c250-160 460-230 680-230 140 0 290 36 460 124l0
170H40z" fill="url(#armG)" opacity=".78"/>
<path d="M110 540c230-200 470-285 720-285 120 0 240 22 370
78v245H110z" fill="rgba(8,8,12,.84)"/>
<path d="M220 540c170-165 360-235 570-235 110 0 220 18 340
64v180H220z" fill="url(#skin)" opacity=".55"/>
</svg>
</article>
</aside>
</section>
</main>
<!-- Controls: replace with your actual images (no external URLs needed) -->
<section class="controls reveal d3" aria-label="Controles para carregar as
imagens">
<div class="ctlGroup">
<label class="file" for="f1">Carregar 1ª foto (moldura)</label>
<input id="f1" type="file" accept="image/*">
<label class="file" for="f2">Carregar 2ª foto (dentro)</label>
<input id="f2" type="file" accept="image/*">
<label class="file" for="f3">Carregar 3ª foto (segurando)</label>
<input id="f3" type="file" accept="image/*">
<label class="file" for="f4">Carregar última foto (fundo)</label>
<input id="f4" type="file" accept="image/*">
<label class="file" for="f5">Carregar dado (anime-style)</label>
<input id="f5" type="file" accept="image/*">
</div>
<button class="btn" id="reset" type="button">Reset</button>
</section>
</div>
<script>
const $ = (id) => [Link](id);
const firstImg = $("firstImg");
const secondImg = $("secondImg");
const thirdImg = $("thirdImg");
const bgLast = $("bgLast");
const diceImg = $("diceImg");
function setBg(el, dataUrl, mode="cover"){
[Link] = `url("${dataUrl}")`;
[Link] = mode;
[Link] = "center";
[Link] = "no-repeat";
}
function bindFile(inputId, apply){
$(inputId).addEventListener("change", (e) => {
const file = [Link] && [Link][0];
if(!file) return;
const reader = new FileReader();
[Link] = () => apply([Link]);
[Link](file);
});
}
// Bind inputs
bindFile("f1", (url) => setBg(firstImg, url, "cover"));
bindFile("f2", (url) => setBg(secondImg, url, "cover"));
bindFile("f3", (url) => setBg(thirdImg, url, "cover"));
bindFile("f4", (url) => setBg(bgLast, url, "cover"));
bindFile("f5", (url) => setBg(diceImg, url, "contain"));
// Quick start: if user pasted images into the chat,
// they still need to download and upload them here (browser security).
// Reset
$("reset").addEventListener("click", () => {
[firstImg, secondImg, thirdImg, bgLast, diceImg].forEach(el => {
[Link] = "none";
[Link] = "";
});
["f1","f2","f3","f4","f5"].forEach(id => $(id).value = "");
});
// Slight parallax on pointer move (subtle, premium)
const cover = [Link](".cover");
let raf = null;
[Link]("pointermove", (e) => {
const r = [Link]();
const x = ([Link] - [Link]) / [Link] - 0.5;
const y = ([Link] - [Link]) / [Link] - 0.5;
if (raf) cancelAnimationFrame(raf);
raf = requestAnimationFrame(() => {
[Link]("--px", [Link](3));
[Link]("--py", [Link](3));
[Link] = `perspective(1200px) rotateX(${(-
y*2.2).toFixed(2)}deg) rotateY(${(x*2.2).toFixed(2)}deg)`;
});
});
[Link]("pointerleave", () => {
[Link] = "none";
});
// Reveal on load
const obs = new IntersectionObserver((entries) => {
[Link](en => {
if([Link]){
[Link] = "running";
[Link]([Link]);
}
});
}, {threshold: .15});
[Link](".reveal").forEach(el => {
[Link] = "running";
[Link](el);
});
</script>
</body>
</html>