TestX / index.html
school44s's picture
Upload 13 files
cee43ad verified
Raw
History Blame Contribute Delete
38.1 kB
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="ANIVIETDB — Vương Tầm Thế Giới. Một trang web, vô vàn thế giới nội dung anime, manga, light novel."
/>
<meta name="theme-color" content="#151515" />
<link
rel="icon"
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='22' fill='%23151515'/><text x='50' y='68' font-size='52' font-family='Arial' font-weight='bold' fill='%23ff5e00' text-anchor='middle'>A</text></svg>"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Grotesk:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<title>ANIVIETDB · Vươn Tầm Thế Giới</title>
<style>
:root {
--cr-bg: #151515;
--cr-ink: #ffffff;
--cr-muted: #8c8c8c;
--cr-subtle: #bbbbbb;
--cr-border: #2a2a2a;
--cr-orange: #ff5e00;
--cr-orange-hover: #ff7a2a;
--cr-accent: #2abdbb;
}
html,
body {
height: 100%;
overflow-x: hidden;
}
body {
background: var(--cr-bg);
color: var(--cr-ink);
font-family: "Inter", system-ui, -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
}
#bg3d {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
}
/* ----- Crunchyroll-style hero (stage 1) ----- */
.cr-hero {
position: relative;
z-index: 1;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
padding: 6.5rem 0 8rem;
background: var(--cr-bg);
}
.cr-wall {
position: absolute;
inset: 0;
z-index: 0;
overflow: hidden;
will-change: transform;
}
.cr-grid {
position: absolute;
inset: -8px;
display: grid;
grid-template-columns: repeat(8, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 2px;
}
.cr-cell {
overflow: hidden;
}
.cr-cell img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
filter: brightness(0.42) saturate(0.65);
opacity: 0.9;
}
.cr-wall::after {
content: "";
position: absolute;
inset: 0;
background:
linear-gradient(180deg, rgba(21, 21, 21, 0.2), rgba(21, 21, 21, 0.72) 68%, #151515 100%),
radial-gradient(120% 90% at 50% 0%, rgba(21, 21, 21, 0) 42%, rgba(21, 21, 21, 0.55) 100%);
}
.cr-hero-inner {
position: relative;
z-index: 2;
}
.cr-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.16);
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(8px);
padding: 0.4rem 0.95rem;
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.03em;
color: var(--cr-subtle);
}
.cr-badge .dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--cr-orange);
animation: cr-pulse 1.6s ease-in-out infinite;
}
@keyframes cr-pulse {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.45;
transform: scale(0.75);
}
}
.cr-title {
font-family: "Space Grotesk", "Inter", sans-serif;
font-weight: 700;
letter-spacing: -0.025em;
font-size: clamp(2.7rem, 9vw, 6rem);
line-height: 1.02;
color: var(--cr-ink);
}
.cr-title .hero-letter {
display: inline-block;
will-change: transform;
}
.cr-title .grad {
background: linear-gradient(92deg, var(--cr-orange) 0%, #ff9a5a 45%, #f0abfc 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.cr-sub {
margin-top: 1.25rem;
max-width: 42rem;
font-size: 1.05rem;
line-height: 1.7;
color: var(--cr-muted);
}
.cr-cta-row {
margin-top: 2.25rem;
display: flex;
flex-wrap: wrap;
gap: 0.9rem;
}
.cr-marquee {
position: absolute;
inset-inline: 0;
bottom: 0;
z-index: 3;
border-top: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(21, 21, 21, 0.55);
backdrop-filter: blur(12px);
padding: 0.95rem 0;
overflow: hidden;
}
.cr-marquee-track {
display: flex;
gap: 2.5rem;
white-space: nowrap;
animation: cr-marquee 30s linear infinite;
will-change: transform;
}
.cr-marquee-item {
display: inline-flex;
align-items: center;
gap: 2.5rem;
font-size: 0.85rem;
font-weight: 500;
letter-spacing: 0.04em;
color: var(--cr-muted);
}
.cr-marquee-item .sep {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--cr-orange);
opacity: 0.75;
}
@keyframes cr-marquee {
to {
transform: translateX(-50%);
}
}
/* ----- shadcn-style Button (primary / outline) ----- */
.btn-cr {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
border-radius: 999px;
font-weight: 600;
font-size: 0.9375rem;
line-height: 1.5;
padding: 0.625rem 1.5rem;
border: 1px solid transparent;
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease,
box-shadow 0.2s ease, transform 0.2s ease;
text-decoration: none;
white-space: nowrap;
user-select: none;
}
.btn-cr:focus-visible {
outline: none;
box-shadow: 0 0 0 2px var(--cr-bg), 0 0 0 4px var(--cr-orange);
}
.btn-cr:disabled {
opacity: 0.5;
pointer-events: none;
}
.btn-cr:hover {
transform: translateY(-1px);
}
.btn-cr-default {
background: var(--cr-orange);
color: #000;
box-shadow: 0 10px 28px rgba(255, 94, 0, 0.32);
}
.btn-cr-default:hover {
background: var(--cr-orange-hover);
color: #000;
box-shadow: 0 12px 32px rgba(255, 94, 0, 0.42);
}
.btn-cr-outline {
border-color: rgba(255, 255, 255, 0.32);
color: var(--cr-ink);
background: transparent;
}
.btn-cr-outline:hover {
border-color: rgba(255, 255, 255, 0.9);
background: rgba(255, 255, 255, 0.07);
color: var(--cr-ink);
}
.btn-cr-lg {
height: 3rem;
padding-inline: 2.1rem;
font-size: 1rem;
border-radius: 999px;
}
/* ----- Feature stage ----- */
.cr-features {
position: relative;
z-index: 1;
background: var(--cr-bg);
padding: 5.5rem 0 6rem;
}
.cr-features-head {
text-align: left;
margin-bottom: 2.5rem;
}
.cr-features-head h2 {
font-family: "Space Grotesk", sans-serif;
font-weight: 700;
font-size: clamp(1.8rem, 4vw, 2.8rem);
letter-spacing: -0.02em;
color: var(--cr-ink);
}
.cr-features-head h2 .grad {
background: linear-gradient(92deg, var(--cr-orange) 0%, #ff9a5a 60%, #f0abfc 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.cr-features-head p {
margin-top: 0.6rem;
color: var(--cr-muted);
font-size: 0.95rem;
}
.cr-feature-row {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 1.25rem;
}
.cr-feature-box {
position: relative;
border-radius: 16px;
overflow: hidden;
aspect-ratio: 2 / 3;
background: #1e1e1e;
border: 1px solid rgba(255, 255, 255, 0.08);
cursor: pointer;
text-decoration: none;
display: flex;
flex-direction: column;
justify-content: flex-end;
will-change: transform;
transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.cr-feature-box:hover {
transform: translateY(-6px);
box-shadow: 0 18px 40px rgba(255, 94, 0, 0.2);
border-color: rgba(255, 94, 0, 0.45);
}
.cr-feature-box img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.35s ease;
}
.cr-feature-box:hover img {
transform: scale(1.06);
}
.cr-feature-box .shade {
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(21, 21, 21, 0.95) 8%, rgba(21, 21, 21, 0.25) 55%, transparent);
}
.cr-feature-box .info {
position: relative;
padding: 1rem 0.9rem;
color: #fff;
}
.cr-feature-box .tag {
display: inline-block;
border-radius: 999px;
background: var(--cr-orange);
color: #000;
font-size: 0.6rem;
font-weight: 700;
letter-spacing: 0.04em;
padding: 0.18rem 0.55rem;
margin-bottom: 0.4rem;
}
.cr-feature-box .t {
font-family: "Space Grotesk", sans-serif;
font-weight: 600;
font-size: 1rem;
line-height: 1.25;
margin: 0;
}
.cr-feature-box .s {
color: rgba(255, 255, 255, 0.7);
font-size: 0.72rem;
margin-top: 0.2rem;
}
.cr-feature-box.fade-in {
opacity: 0;
transform: translateY(28px);
}
.cr-feature-box.fade-in.visible {
opacity: 1;
transform: translateY(0);
transition: opacity 0.6s ease, transform 0.6s ease, box-shadow 0.25s ease,
border-color 0.25s ease;
}
/* ----- Shop stage (stage 3) ----- */
.cr-shop {
position: relative;
z-index: 1;
background: linear-gradient(180deg, var(--cr-bg) 0%, #171719 100%);
padding: 5.5rem 0 6rem;
}
.cr-shop-head {
text-align: center;
margin-bottom: 2.5rem;
}
.cr-shop-head h2 {
font-family: "Space Grotesk", sans-serif;
font-weight: 700;
font-size: clamp(1.8rem, 4vw, 2.8rem);
letter-spacing: -0.02em;
color: var(--cr-ink);
}
.cr-shop-head h2 .grad {
background: linear-gradient(92deg, var(--cr-orange) 0%, #ff9a5a 60%, #f0abfc 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.cr-shop-head p {
margin-top: 0.6rem;
color: var(--cr-muted);
font-size: 0.95rem;
}
.cr-shop-row {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1.25rem;
}
.cr-shop-card {
border-radius: 16px;
overflow: hidden;
background: #1d1d1f;
border: 1px solid rgba(255, 255, 255, 0.08);
text-decoration: none;
display: flex;
flex-direction: column;
transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
cursor: pointer;
}
.cr-shop-card:hover {
transform: translateY(-6px);
box-shadow: 0 18px 40px rgba(255, 94, 0, 0.18);
border-color: rgba(255, 94, 0, 0.45);
}
.cr-shop-card .pic {
position: relative;
aspect-ratio: 1 / 1;
background: #141416;
overflow: hidden;
}
.cr-shop-card .pic img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.35s ease;
}
.cr-shop-card:hover .pic img {
transform: scale(1.07);
}
.cr-shop-card .pic .cat {
position: absolute;
top: 0.6rem;
left: 0.6rem;
border-radius: 999px;
background: rgba(21, 21, 21, 0.75);
color: var(--cr-orange);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.04em;
padding: 0.2rem 0.6rem;
backdrop-filter: blur(4px);
}
.cr-shop-card .pic .price {
position: absolute;
bottom: 0.6rem;
right: 0.6rem;
border-radius: 10px;
background: var(--cr-orange);
color: #000;
font-weight: 800;
font-size: 0.8rem;
padding: 0.3rem 0.65rem;
}
.cr-shop-card .meta {
padding: 0.9rem 1rem 1.1rem;
}
.cr-shop-card .meta .t {
font-family: "Space Grotesk", sans-serif;
font-weight: 600;
font-size: 0.95rem;
color: #fff;
margin: 0 0 0.15rem;
}
.cr-shop-card .meta .s {
color: var(--cr-muted);
font-size: 0.75rem;
}
.cr-shop-card.fade-in {
opacity: 0;
transform: translateY(28px);
}
.cr-shop-card.fade-in.visible {
opacity: 1;
transform: translateY(0);
transition: opacity 0.6s ease, transform 0.6s ease, box-shadow 0.25s ease,
border-color 0.25s ease;
}
.cr-shop-cta {
margin-top: 2.75rem;
text-align: center;
}
/* ----- Footer ----- */
.cr-footer {
position: relative;
z-index: 1;
border-top: 1px solid rgba(255, 255, 255, 0.08);
background: var(--cr-bg);
padding: 3.25rem 1.5rem 3rem;
text-align: center;
}
.cr-footer p {
max-width: 46rem;
margin-inline: auto;
color: var(--cr-muted);
font-size: 0.85rem;
line-height: 1.7;
}
.cr-footer p + p {
margin-top: 0.35rem;
color: var(--cr-subtle);
font-size: 0.8rem;
}
.cr-footer .brand {
font-family: "Space Grotesk", sans-serif;
font-weight: 700;
font-size: 1rem;
letter-spacing: 0.06em;
color: var(--cr-ink);
margin-bottom: 0.9rem;
}
.cr-footer .brand span {
color: var(--cr-orange);
}
@media (max-width: 767.98px) {
.cr-hero {
padding-top: 5rem;
}
.cr-grid {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(6, 1fr);
}
.cr-feature-row {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.9rem;
}
.cr-shop-row {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.9rem;
}
}
</style>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@18.3.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script>
(function () {
var React = window.React;
var ReactDOM = window.ReactDOM;
var e = React.createElement;
var useRef = React.useRef;
var useEffect = React.useEffect;
var POSTERS = [
"https://phim.nguonc.com/public/images/Film/76.jpg",
"https://phim.nguonc.com/public/images/Film/666.jpg",
"https://phim.nguonc.com/public/images/Film/77.jpg",
"https://phim.nguonc.com/public/images/Film/667.jpg",
"https://phim.nguonc.com/public/images/Film/259.jpg",
"https://phim.nguonc.com/public/images/Film/2738.jpg",
"https://phim.nguonc.com/public/images/Film/3485.jpg",
"https://phim.nguonc.com/public/images/Film/141438.jpg",
"https://phim.nguonc.com/public/images/Film/date-a-bullet-thumb.jpg",
"https://phim.nguonc.com/public/images/Film/3103.jpg",
"https://phim.nguonc.com/public/images/Post/5/aishiteru-game-wo-owarasetai.jpg",
"https://phim.nguonc.com/public/images/Film/541.jpg",
"https://phim.nguonc.com/public/images/Film/536.jpg",
"https://phim.nguonc.com/public/images/Film/56167.jpg",
"https://phim.nguonc.com/public/images/Film/56643.jpg",
"https://phim.nguonc.com/public/images/Film/538.jpg",
"https://phim.nguonc.com/public/images/Film/540.jpg",
"https://phim.nguonc.com/public/images/Film/60351.jpg",
"https://phim.nguonc.com/public/images/Film/2607.jpg",
"https://phim.nguonc.com/public/images/Film/2661.jpg",
"https://phim.nguonc.com/public/images/Film/5MgMCnslrxQfOfaq6T5ndkLlcCk.jpg",
"https://phim.nguonc.com/public/images/Film/134808.jpg",
"https://phim.nguonc.com/public/images/Film/138379.jpg",
"https://phim.nguonc.com/public/images/Post/9/seishun-buta-yarou-wa-santa-claus-no-yume-wo-minai-1.jpg"
];
var MARQUEE = [
"Anime",
"Manga",
"Manhwa",
"Manhua",
"Light Novel",
"Sưu tầm",
"Vô vàn thế giới"
];
var FEATURES = [
{ name: "Death Note", sub: "37 tập", tag: "Anime", page: "sfw/anime/universal/death-note/", img: "https://phim.nguonc.com/public/images/Film/244.jpg" },
{ name: "Tensei Slime", sub: "24 tập", tag: "Anime", page: "sfw/anime/universal/tensei-slime/phan-1/", img: "https://phim.nguonc.com/public/images/Film/2658.jpg" },
{ name: "JoJo Phần 1", sub: "26 tập", tag: "Anime", page: "sfw/anime/universal/jojo/phan-1/", img: "https://phim.nguonc.com/public/images/Film/40409.jpg" },
{ name: "Fate/Zero", sub: "13 tập", tag: "Anime", page: "sfw/anime/multiversal/fate/fate-zero/phan-1/", img: "https://phim.nguonc.com/public/images/Film/117644.jpg" },
{ name: "Bocchi the Rock!", sub: "12 tập", tag: "Anime", page: "sfw/anime/universal/bocchi-the-rock/phan-1/", img: "https://phim.nguonc.com/public/images/Film/127956.jpg" }
];
var SHOP_PRODUCTS = [
{ name: "Figure Gojo Satoru", anime: "Jujutsu Kaisen", cat: "Figure", price: "1.290.000đ", img: "https://phim.nguonc.com/public/images/Film/76.jpg" },
{ name: "Figure Luffy Gear 5", anime: "One Piece", cat: "Figure", price: "1.450.000đ", img: "https://phim.nguonc.com/public/images/Film/666.jpg" },
{ name: "Plushie Anya Forger", anime: "Spy x Family", cat: "Plushie", price: "350.000đ", img: "https://phim.nguonc.com/public/images/Film/3485.jpg" },
{ name: "Mug Steins;Gate", anime: "Steins;Gate", cat: "Mug", price: "185.000đ", img: "https://phim.nguonc.com/public/images/Film/536.jpg" }
];
function cx() {
return Array.prototype.filter.call(arguments, Boolean).join(" ");
}
function Button(props) {
var className = cx(
"btn-cr",
"btn-cr-" + (props.variant || "default"),
(props.size || "default") === "lg" ? "btn-cr-lg" : "",
props.className
);
var p = {};
for (var k in props) {
if (k === "variant" || k === "size" || k === "className" || k === "children") continue;
p[k] = props[k];
}
return e("button", Object.assign({}, p, { className: className }), props.children);
}
function ThreeBackground() {
var ref = useRef(null);
useEffect(function () {
var canvas = ref.current;
var renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true,
antialias: true
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
var w = window.innerWidth;
var h = window.innerHeight;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(70, w / h, 0.1, 40);
camera.position.z = 1;
function onResize() {
w = window.innerWidth;
h = window.innerHeight;
renderer.setSize(w, h);
camera.aspect = w / h;
camera.updateProjectionMatrix();
}
onResize();
window.addEventListener("resize", onResize);
var COUNT = 1400;
var positions = new Float32Array(COUNT * 3);
for (var i = 0; i < COUNT * 3; i++) positions[i] = (Math.random() - 0.5) * 4;
var geo = new THREE.BufferGeometry();
geo.setAttribute("position", new THREE.BufferAttribute(positions, 3));
var mat = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.004,
transparent: true,
opacity: 0.65,
sizeAttenuation: true
});
var stars = new THREE.Points(geo, mat);
scene.add(stars);
var glow = new THREE.Mesh(
new THREE.SphereGeometry(0.16, 32, 32),
new THREE.MeshBasicMaterial({
color: 0xff5e00,
transparent: true,
opacity: 0.16
})
);
glow.position.set(0.9, 0.55, -0.6);
scene.add(glow);
var raf;
var mx = 0;
var my = 0;
function onMouse(e2) {
mx = (e2.clientX / w - 0.5) * 2;
my = (e2.clientY / h - 0.5) * 2;
}
window.addEventListener("mousemove", onMouse);
function tick() {
stars.rotation.y += 0.00022;
stars.rotation.x += 0.00008;
camera.position.x += (mx * 0.05 - camera.position.x) * 0.04;
camera.position.y += (-my * 0.05 - camera.position.y) * 0.04;
camera.lookAt(0, 0, 0);
renderer.render(scene, camera);
raf = requestAnimationFrame(tick);
}
tick();
return function () {
cancelAnimationFrame(raf);
window.removeEventListener("resize", onResize);
window.removeEventListener("mousemove", onMouse);
renderer.dispose();
};
}, []);
return e("canvas", { id: "bg3d", ref: ref });
}
function Hero() {
var wallRef = useRef(null);
useEffect(function () {
var letters = gsap.utils.toArray(".hero-letter");
var reveals = gsap.utils.toArray(".cr-reveal");
gsap.set(letters, { yPercent: 115, opacity: 0 });
gsap.set(reveals, { y: 26, opacity: 0 });
var tl = gsap.timeline({ defaults: { ease: "power3.out" } });
tl.to(letters, { yPercent: 0, opacity: 1, stagger: 0.05, duration: 0.85 }, 0.2)
.to(reveals, { y: 0, opacity: 1, stagger: 0.1, duration: 0.6 }, 0.6)
.fromTo(
wallRef.current,
{ scale: 1.22 },
{ scale: 1.02, duration: 2.4, ease: "power2.out" },
0
);
return function () {
tl.kill();
};
}, []);
var brand = "ANIVIETDB".split("");
var heroLetters = brand.map(function (c, i) {
return e("span", { className: "hero-letter", key: i }, c);
});
return e(
"section",
{ className: "cr-hero" },
e(
"div",
{ className: "cr-wall", ref: wallRef },
e(
"div",
{ className: "cr-grid" },
POSTERS.map(function (u, i) {
return e(
"div",
{ className: "cr-cell", key: i },
e("img", { src: u, alt: "", loading: "lazy" })
);
})
)
),
e(
"div",
{ className: "cr-hero-inner container" },
e(
"div",
{ className: "row" },
e(
"div",
{ className: "col-12 col-lg-9 col-xl-8" },
e(
"span",
{ className: "cr-badge cr-reveal" },
e("span", { className: "dot" }),
" Giới thiệu · Vươn Tầm Thế Giới"
),
e(
"h1",
{ className: "cr-title" },
heroLetters,
e(
"span",
{ className: "d-block" },
e("span", { className: "grad" }, "Vươn Tầm Thế Giới")
)
),
e(
"p",
{ className: "cr-sub cr-reveal" },
"Nơi hội tụ anime, manga, webtoon và light novel — một trang web, vô vàn thế giới."
),
e(
"div",
{ className: "cr-cta-row cr-reveal" },
e(
Button,
{ size: "lg", onClick: function () { openSfwWithLoginCheck(); } },
"Bắt đầu"
),
e(
Button,
{
size: "lg",
variant: "outline",
onClick: function () {
var el = document.getElementById("featureStage");
if (el) el.scrollIntoView({ behavior: "smooth" });
}
},
"Xem phim nổi bật"
)
)
)
)
),
e(
"div",
{ className: "cr-marquee" },
e(
"div",
{ className: "cr-marquee-track" },
MARQUEE.concat(MARQUEE).map(function (w, i) {
return e(
"span",
{ className: "cr-marquee-item", key: i },
w,
e("span", { className: "sep" })
);
})
)
)
);
}
function FeatureStage() {
var secRef = useRef(null);
useEffect(function () {
var boxes = secRef.current ? secRef.current.querySelectorAll(".cr-feature-box.fade-in") : [];
if (!("IntersectionObserver" in window)) {
Array.prototype.forEach.call(boxes, function (b) { b.classList.add("visible"); });
return;
}
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.classList.add("visible");
io.unobserve(en.target);
}
});
},
{ threshold: 0.15 }
);
Array.prototype.forEach.call(boxes, function (b) { io.observe(b); });
return function () { io.disconnect(); };
}, []);
return e(
"section",
{ id: "featureStage", className: "cr-features", ref: secRef },
e(
"div",
{ className: "container" },
e(
"div",
{ className: "cr-features-head" },
e("h2", null, "Phim nổi bật ", e("span", { className: "grad" }, "Feature")),
e(
"p",
null,
"Những tựa anime đáng xem nhất, cập nhật liên tục từ ANIVIETDB."
)
),
e(
"div",
{ className: "cr-feature-row" },
FEATURES.map(function (f, i) {
return e(
"a",
{
key: i,
href: f.page,
className: "cr-feature-box fade-in",
style: { transitionDelay: i * 0.08 + "s" }
},
e("img", { src: f.img, alt: f.name, loading: "lazy" }),
e("div", { className: "shade" }),
e(
"div",
{ className: "info" },
e("span", { className: "tag" }, f.tag),
e("p", { className: "t" }, f.name),
e("p", { className: "s" }, f.sub)
)
);
})
)
)
);
}
function openWithLoginCheck(url) {
function go() { window.location.href = url; }
function showPopup() {
var m = document.getElementById("loginReqPopup");
m.classList.add("active");
}
if (window.AuthSystem) {
window.AuthSystem.me().then(function (user) {
if (user) { go(); } else { showPopup(); }
}).catch(function () { showPopup(); });
return;
}
var s = document.createElement("script");
s.src = "signup-loginsystem.js";
s.onload = function () {
if (window.AuthSystem) {
window.AuthSystem.me().then(function (user) {
if (user) { go(); } else { showPopup(); }
}).catch(function () { showPopup(); });
} else {
showPopup();
}
};
s.onerror = function () { showPopup(); };
document.head.appendChild(s);
}
function openShopWithLoginCheck() { openWithLoginCheck("shop/index.html"); }
function openSfwWithLoginCheck() {
function go() { window.location.href = "sfw/index.html"; }
function goLogin() { window.location.href = "login.html"; }
function check() {
window.AuthSystem.me().then(function (user) {
if (user) { go(); } else { goLogin(); }
}).catch(function () { goLogin(); });
}
if (window.AuthSystem) { check(); return; }
var s = document.createElement("script");
s.src = "signup-loginsystem.js";
s.onload = function () { if (window.AuthSystem) { check(); } else { goLogin(); } };
s.onerror = function () { goLogin(); };
document.head.appendChild(s);
}
function ShopStage() {
var secRef = useRef(null);
useEffect(function () {
var cards = secRef.current ? secRef.current.querySelectorAll(".cr-shop-card.fade-in") : [];
if (!("IntersectionObserver" in window)) {
Array.prototype.forEach.call(cards, function (b) { b.classList.add("visible"); });
return;
}
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.classList.add("visible");
io.unobserve(en.target);
}
});
},
{ threshold: 0.15 }
);
Array.prototype.forEach.call(cards, function (b) { io.observe(b); });
return function () { io.disconnect(); };
}, []);
return e(
"section",
{ id: "shopStage", className: "cr-shop", ref: secRef },
e(
"div",
{ className: "container" },
e(
"div",
{ className: "cr-shop-head" },
e("h2", null, "Figure Shop ", e("span", { className: "grad" }, "ANIVIETDB")),
e(
"p",
null,
"Figure, plushie, manga, Blu-ray và đồ lưu niệm sưu tầm — khám phá ngay, đặt mua tại cửa hàng."
)
),
e(
"div",
{ className: "cr-shop-row" },
SHOP_PRODUCTS.map(function (f, i) {
return e(
"a",
{
key: i,
href: "shop/index.html",
className: "cr-shop-card fade-in",
style: { transitionDelay: i * 0.08 + "s" }
},
e(
"div",
{ className: "pic" },
e("span", { className: "cat" }, f.cat),
e("img", { src: f.img, alt: f.name, loading: "lazy" }),
e("span", { className: "price" }, f.price)
),
e(
"div",
{ className: "meta" },
e("p", { className: "t" }, f.name),
e("p", { className: "s" }, f.anime)
)
);
})
),
e(
"div",
{ className: "cr-shop-cta" },
e(
Button,
{
size: "lg",
onClick: function () { openShopWithLoginCheck(); }
},
"Khám phá shop"
)
)
)
);
}
function Footer() {
return e(
"footer",
{ className: "cr-footer" },
e(
"p",
{ className: "brand" },
"ANIVIETDB ",
e("span", null, "·"),
" Vươn Tầm Thế Giới"
),
e(
"p",
null,
"© 2026 ANIVIETDB. Tất cả nội dung Anime, Manga, Manhwa, Manhua và Light Novel được sưu tầm và thuộc bản quyền của chủ sở hữu tương ứng."
),
e(
"p",
null,
"Trang web sưu tầm cá nhân - Phi thương mại. Mọi quyền được bảo lưu."
)
);
}
function App() {
return e(
"main",
{ className: "position-relative" },
e(ThreeBackground),
e(Hero),
e(FeatureStage),
e(ShopStage),
e(Footer)
);
}
ReactDOM.createRoot(document.getElementById("root")).render(e(App));
})();
</script>
<div class="login-req-overlay" id="loginReqPopup">
<div class="login-req-popup">
<h3>&#128274; Bạn chưa đăng nhập</h3>
<p>Hãy đăng nhập để khám phá cửa hàng ANIVIETDB và đặt mua sản phẩm.</p>
<div class="login-req-actions">
<button class="login-req-btn" id="loginReqGo">Bắt đầu đăng nhập</button>
<button class="login-req-btn login-req-ghost" id="loginReqClose">Để sau</button>
</div>
</div>
</div>
<style>
.login-req-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.7); display: none; align-items: center; justify-content: center; z-index: 10000; backdrop-filter: blur(4px); }
.login-req-overlay.active { display: flex; }
.login-req-popup { background: #1d1d1d; border: 1px solid var(--cr-border); border-radius: 16px; padding: 30px 36px; text-align: center; color: var(--cr-ink); font-family: "Inter", system-ui, sans-serif; max-width: 380px; box-shadow: 0 20px 60px rgba(0,0,0,.6); }
.login-req-popup h3 { margin: 0 0 10px; font-size: 20px; font-weight: 700; }
.login-req-popup p { margin: 0 0 22px; color: var(--cr-muted); font-size: 14px; line-height: 1.6; }
.login-req-actions { display: flex; flex-direction: column; gap: 10px; }
.login-req-btn { background: var(--cr-orange); color: #fff; border: none; padding: 12px 20px; border-radius: 10px; font-weight: 600; font-size: 15px; cursor: pointer; transition: background .15s; }
.login-req-btn:hover { background: var(--cr-orange-hover); }
.login-req-btn.login-req-ghost { background: none; color: var(--cr-muted); border: 1px solid var(--cr-border); }
.login-req-btn.login-req-ghost:hover { color: #fff; border-color: #555; }
</style>
<script>
(function () {
var overlay = document.getElementById("loginReqPopup");
var goBtn = document.getElementById("loginReqGo");
var closeBtn = document.getElementById("loginReqClose");
if (goBtn) goBtn.addEventListener("click", function () {
window.location.href = "login.html";
});
if (closeBtn) closeBtn.addEventListener("click", function () {
overlay.classList.remove("active");
});
if (overlay) overlay.addEventListener("click", function (e) {
if (e.target === overlay) overlay.classList.remove("active");
});
})();
</script>
</body>
</html>