1163 lines
36 KiB
HTML
1163 lines
36 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Vessel — New Release</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<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=Playfair+Display:wght@400;700;900&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--bg: #0c0c0c;
|
|
--bg-elevated: #141414;
|
|
--fg: #f0e8d8;
|
|
--muted: #8a7e6f;
|
|
--accent: #c9974e;
|
|
--accent-light: #e0b87a;
|
|
--card: #1a1a1a;
|
|
--border: #2a2a2a;
|
|
}
|
|
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
html { scroll-behavior: smooth; }
|
|
|
|
body {
|
|
font-family: 'Inter', sans-serif;
|
|
background: var(--bg);
|
|
color: var(--fg);
|
|
overflow-x: hidden;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 { font-family: 'Playfair Display', serif; }
|
|
|
|
/* Scroll progress */
|
|
#scroll-progress {
|
|
position: fixed; top: 0; left: 0; height: 3px;
|
|
background: var(--accent);
|
|
z-index: 1000;
|
|
width: 0%;
|
|
transition: width 0.1s linear;
|
|
}
|
|
|
|
/* Loading screen */
|
|
#loader {
|
|
position: fixed; inset: 0; z-index: 9999;
|
|
background: var(--bg);
|
|
display: flex; align-items: center; justify-content: center;
|
|
flex-direction: column; gap: 1.5rem;
|
|
transition: opacity 0.6s ease;
|
|
}
|
|
#loader.hidden { opacity: 0; pointer-events: none; }
|
|
|
|
.loader-ring {
|
|
width: 48px; height: 48px;
|
|
border: 2px solid var(--border);
|
|
border-top-color: var(--accent);
|
|
border-radius: 50%;
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
|
|
/* Hero */
|
|
.hero-section {
|
|
position: relative;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.hero-bg {
|
|
position: absolute; inset: 0;
|
|
background: linear-gradient(135deg, #1a1410 0%, #0c0c0c 40%, #1a1410 100%);
|
|
}
|
|
|
|
.hero-grain {
|
|
position: absolute; inset: 0;
|
|
opacity: 0.04;
|
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
|
background-size: 200px 200px;
|
|
}
|
|
|
|
.hero-orb {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
filter: blur(80px);
|
|
opacity: 0.3;
|
|
animation: float 8s ease-in-out infinite;
|
|
}
|
|
|
|
.hero-orb-1 {
|
|
width: 400px; height: 400px;
|
|
background: var(--accent);
|
|
top: 10%; left: 15%;
|
|
}
|
|
|
|
.hero-orb-2 {
|
|
width: 300px; height: 300px;
|
|
background: #3a2a1a;
|
|
bottom: 20%; right: 10%;
|
|
animation-delay: -3s;
|
|
}
|
|
|
|
.hero-content {
|
|
position: relative;
|
|
z-index: 2;
|
|
text-align: center;
|
|
max-width: 900px;
|
|
padding: 0 2rem;
|
|
}
|
|
|
|
.hero-label {
|
|
font-size: 0.85rem;
|
|
letter-spacing: 0.3em;
|
|
text-transform: uppercase;
|
|
color: var(--muted);
|
|
margin-bottom: 1rem;
|
|
animation: fadeUp 1s ease 0.3s both;
|
|
}
|
|
|
|
.hero-title {
|
|
font-size: clamp(3rem, 8vw, 6.5rem);
|
|
font-weight: 900;
|
|
line-height: 1.05;
|
|
letter-spacing: -0.02em;
|
|
margin-bottom: 1rem;
|
|
animation: fadeUp 1s ease 0.5s both;
|
|
}
|
|
|
|
.hero-title .highlight {
|
|
color: var(--accent);
|
|
position: relative;
|
|
}
|
|
|
|
.hero-title .highlight::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0.15em;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 2px;
|
|
background: var(--accent);
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.hero-sub {
|
|
font-size: clamp(1rem, 2vw, 1.25rem);
|
|
color: var(--muted);
|
|
font-weight: 300;
|
|
margin-bottom: 2.5rem;
|
|
animation: fadeUp 1s ease 0.7s both;
|
|
}
|
|
|
|
.hero-cta {
|
|
display: inline-block;
|
|
padding: 0.9rem 2.2rem;
|
|
background: var(--accent);
|
|
color: var(--bg);
|
|
font-weight: 600;
|
|
font-size: 0.95rem;
|
|
border-radius: 0;
|
|
transition: all 0.3s ease;
|
|
text-decoration: none;
|
|
animation: fadeUp 1s ease 0.9s both;
|
|
}
|
|
|
|
.hero-cta:hover {
|
|
background: var(--accent-light);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 30px rgba(201,151,78,0.3);
|
|
}
|
|
|
|
.hero-scroll {
|
|
position: absolute;
|
|
bottom: 2rem;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
animation: bounce 2s ease-in-out infinite;
|
|
z-index: 2;
|
|
}
|
|
|
|
.hero-scroll svg {
|
|
width: 24px; height: 24px;
|
|
stroke: var(--muted);
|
|
}
|
|
|
|
/* Section styles */
|
|
.section {
|
|
padding: 6rem 2rem;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.section-label {
|
|
font-size: 0.75rem;
|
|
letter-spacing: 0.25em;
|
|
text-transform: uppercase;
|
|
color: var(--accent);
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: clamp(2rem, 4vw, 3.2rem);
|
|
font-weight: 700;
|
|
line-height: 1.15;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.section-desc {
|
|
color: var(--muted);
|
|
max-width: 600px;
|
|
font-size: 1.05rem;
|
|
}
|
|
|
|
/* Track cards */
|
|
.tracks-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-top: 2.5rem;
|
|
}
|
|
|
|
.track-card {
|
|
background: var(--card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1);
|
|
cursor: pointer;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.track-card::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(135deg, rgba(201,151,78,0.05) 0%, transparent 60%);
|
|
opacity: 0;
|
|
transition: opacity 0.4s ease;
|
|
}
|
|
|
|
.track-card:hover {
|
|
border-color: var(--accent);
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 16px 40px rgba(0,0,0,0.5);
|
|
}
|
|
|
|
.track-card:hover::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
.track-number {
|
|
font-family: 'Inter', sans-serif;
|
|
font-size: 0.75rem;
|
|
color: var(--muted);
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.track-title {
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
margin-bottom: 0.3rem;
|
|
}
|
|
|
|
.track-artist {
|
|
font-size: 0.85rem;
|
|
color: var(--muted);
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.track-duration {
|
|
font-size: 0.75rem;
|
|
color: var(--muted);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.track-duration svg {
|
|
width: 12px; height: 12px;
|
|
stroke: var(--muted);
|
|
}
|
|
|
|
/* Duration icon */
|
|
.duration-icon {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.duration-icon svg {
|
|
width: 14px; height: 14px;
|
|
stroke: var(--muted);
|
|
}
|
|
|
|
/* Artist profile */
|
|
.artist-profile {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 2rem;
|
|
padding: 2rem;
|
|
background: var(--card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 16px;
|
|
margin-top: 2.5rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.artist-avatar {
|
|
width: 100px; height: 100px;
|
|
border-radius: 50%;
|
|
border: 3px solid var(--accent);
|
|
overflow: hidden;
|
|
flex-shrink: 0;
|
|
background: var(--bg-elevated);
|
|
}
|
|
|
|
.artist-avatar img {
|
|
width: 100%; height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.artist-info h3 {
|
|
font-size: 1.5rem;
|
|
font-weight: 700;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.artist-info .artist-bio {
|
|
color: var(--muted);
|
|
font-size: 0.95rem;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.artist-info .artist-meta {
|
|
display: flex;
|
|
gap: 1rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.artist-meta-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
color: var(--muted);
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.artist-meta-item svg {
|
|
width: 14px; height: 14px;
|
|
stroke: var(--muted);
|
|
}
|
|
|
|
.artist-meta-item strong {
|
|
color: var(--fg);
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* Info grid */
|
|
.info-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-top: 2.5rem;
|
|
}
|
|
|
|
.info-item {
|
|
background: var(--card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 10px;
|
|
padding: 1.5rem;
|
|
text-align: center;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.info-item:hover {
|
|
border-color: var(--accent);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.info-item .info-icon {
|
|
width: 44px; height: 44px;
|
|
margin: 0 auto 0.75rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(201,151,78,0.1);
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.info-item .info-icon svg {
|
|
width: 22px; height: 22px;
|
|
stroke: var(--accent);
|
|
}
|
|
|
|
.info-item .info-value {
|
|
font-size: 1.3rem;
|
|
font-weight: 700;
|
|
color: var(--accent);
|
|
margin-bottom: 0.15rem;
|
|
}
|
|
|
|
.info-item .info-label {
|
|
font-size: 0.8rem;
|
|
color: var(--muted);
|
|
}
|
|
|
|
/* Buttons */
|
|
.btn-primary {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.85rem 1.8rem;
|
|
background: var(--accent);
|
|
color: var(--bg);
|
|
font-weight: 600;
|
|
font-size: 0.95rem;
|
|
border-radius: 0;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background: var(--accent-light);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 24px rgba(201,151,78,0.3);
|
|
}
|
|
|
|
.btn-outline {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.85rem 1.8rem;
|
|
background: transparent;
|
|
color: var(--fg);
|
|
font-weight: 500;
|
|
font-size: 0.95rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: 0;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-outline:hover {
|
|
border-color: var(--accent);
|
|
color: var(--accent);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
/* Image styles */
|
|
.image-cover {
|
|
position: relative;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.image-cover img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
transition: transform 0.6s ease;
|
|
}
|
|
|
|
.image-cover:hover img {
|
|
transform: scale(1.03);
|
|
}
|
|
|
|
.image-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 50%);
|
|
border-radius: 12px;
|
|
}
|
|
|
|
/* Floating particles */
|
|
.particle {
|
|
position: absolute;
|
|
width: 3px; height: 3px;
|
|
background: var(--accent);
|
|
border-radius: 50%;
|
|
opacity: 0;
|
|
animation: particle-float 6s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes particle-float {
|
|
0% { opacity: 0; transform: translateY(0) scale(0); }
|
|
30% { opacity: 0.6; }
|
|
70% { opacity: 0.3; }
|
|
100% { opacity: 0; transform: translateY(-200px) scale(1.5); }
|
|
}
|
|
|
|
/* Noise texture */
|
|
.noise-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 9998;
|
|
pointer-events: none;
|
|
opacity: 0.03;
|
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
|
background-size: 256px 256px;
|
|
}
|
|
|
|
/* Wave animation */
|
|
.wave-bar {
|
|
display: inline-block;
|
|
width: 3px;
|
|
background: var(--accent);
|
|
border-radius: 2px;
|
|
margin: 0 1px;
|
|
transition: height 0.15s ease;
|
|
}
|
|
|
|
.wave-bar.active {
|
|
animation: wave 0.6s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes wave {
|
|
0%, 100% { height: 4px; }
|
|
50% { height: 20px; }
|
|
}
|
|
|
|
/* Parallax */
|
|
.parallax-section {
|
|
will-change: transform;
|
|
}
|
|
|
|
/* Toast */
|
|
.toast {
|
|
position: fixed;
|
|
bottom: 2rem;
|
|
right: 2rem;
|
|
background: var(--card);
|
|
border: 1px solid var(--accent);
|
|
border-radius: 10px;
|
|
padding: 1rem 1.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
z-index: 1000;
|
|
transform: translateX(120%);
|
|
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
|
|
box-shadow: 0 8px 30px rgba(0,0,0,0.4);
|
|
}
|
|
|
|
.toast.show {
|
|
transform: translateX(0);
|
|
}
|
|
|
|
.toast svg {
|
|
width: 20px; height: 20px;
|
|
stroke: var(--accent);
|
|
}
|
|
|
|
/* Footer */
|
|
.site-footer {
|
|
padding: 3rem 2rem;
|
|
border-top: 1px solid var(--border);
|
|
margin-top: 3rem;
|
|
max-width: 1200px;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
}
|
|
|
|
.footer-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 2rem;
|
|
}
|
|
|
|
.footer-brand h3 {
|
|
font-size: 1.25rem;
|
|
font-weight: 700;
|
|
color: var(--fg);
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.footer-brand p {
|
|
color: var(--muted);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.footer-links {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.footer-links a {
|
|
color: var(--muted);
|
|
font-size: 0.85rem;
|
|
text-decoration: none;
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
.footer-links a:hover {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.footer-bottom {
|
|
margin-top: 2rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid var(--border);
|
|
text-align: center;
|
|
color: var(--muted);
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
/* Scroll reveal */
|
|
.reveal {
|
|
opacity: 0;
|
|
transform: translateY(30px);
|
|
transition: opacity 0.8s ease, transform 0.8s ease;
|
|
}
|
|
|
|
.reveal.visible {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.artist-profile { flex-direction: column; text-align: center; }
|
|
.artist-avatar { width: 140px; height: 140px; }
|
|
.info-grid { grid-template-columns: repeat(2, 1fr); }
|
|
.hero-orb-1 { width: 250px; height: 250px; }
|
|
.hero-orb-2 { width: 200px; height: 200px; }
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.hero-title { font-size: 2.5rem; }
|
|
.tracks-grid { grid-template-columns: 1fr; }
|
|
.info-grid { grid-template-columns: 1fr; }
|
|
.footer-grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* Reduced motion */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*, *::before, *::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
}
|
|
}
|
|
|
|
/* Focus styles */
|
|
*:focus-visible {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: 3px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="loader" aria-label="Loading">
|
|
<div class="loader-ring"></div>
|
|
<span class="text-sm" style="color: var(--muted);">Loading the next chapter...</span>
|
|
</div>
|
|
|
|
<div id="scroll-progress" aria-hidden="true"></div>
|
|
<div class="noise-overlay" aria-hidden="true"></div>
|
|
|
|
<!-- Toast notification -->
|
|
<div class="toast" id="toast" role="alert" aria-live="polite">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
|
<polyline points="22 4 12 14.01 9 11.01"/>
|
|
</svg>
|
|
<span id="toast-msg">Track added to your queue</span>
|
|
</div>
|
|
|
|
<!-- Navigation -->
|
|
<nav class="fixed top-0 left-0 right-0 z-50 transition-all duration-300" id="navbar" style="background: rgba(12,12,12,0.85); backdrop-filter: blur(16px); border-bottom: 1px solid transparent;" aria-label="Main navigation">
|
|
<div class="max-w-6xl mx-auto px-6 flex items-center justify-between h-16">
|
|
<a href="#" class="flex items-center gap-2" aria-label="Vessel Home">
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 6v6l4 2"/>
|
|
</svg>
|
|
<span class="font-bold text-lg" style="color: var(--fg);">Vessel</span>
|
|
</a>
|
|
|
|
<div class="hidden md:flex items-center gap-8">
|
|
<a href="#tracks" class="text-sm" style="color: var(--muted); text-decoration: none; transition: color 0.3s;">Tracks</a>
|
|
<a href="#artist" class="text-sm" style="color: var(--muted); text-decoration: none; transition: color 0.3s;">About</a>
|
|
<a href="#info" class="text-sm" style="color: var(--muted); text-decoration: none; transition: color 0.3s;">Details</a>
|
|
<button class="btn-primary text-sm" style="padding: 0.5rem 1.2rem; font-size: 0.85rem;" onclick="showToast('Track queue updated')">
|
|
Queue Now
|
|
</button>
|
|
</div>
|
|
|
|
<button class="md:hidden" id="mobile-menu-btn" aria-label="Toggle menu" style="background: none; border: none; color: var(--fg); font-size: 1.5rem; cursor: pointer;">
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
<line x1="3" y1="12" x2="21" y2="12"/>
|
|
<line x1="3" y1="18" x2="21" y2="18"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="md:hidden hidden" id="mobile-menu">
|
|
<div class="px-6 py-4 flex flex-col gap-4">
|
|
<a href="#tracks" class="text-sm" style="color: var(--muted); text-decoration: none;">Tracks</a>
|
|
<a href="#artist" class="text-sm" style="color: var(--muted); text-decoration: none;">About</a>
|
|
<a href="#info" class="text-sm" style="color: var(--muted); text-decoration: none;">Details</a>
|
|
<button class="btn-primary text-sm" style="padding: 0.5rem 1.2rem; font-size: 0.85rem; align-self: center;">Queue Now</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Hero Section -->
|
|
<section class="hero-section" aria-label="Hero">
|
|
<div class="hero-bg" aria-hidden="true"></div>
|
|
<div class="hero-grain" aria-hidden="true"></div>
|
|
<div class="hero-orb hero-orb-1" aria-hidden="true"></div>
|
|
<div class="hero-orb hero-orb-2" aria-hidden="true"></div>
|
|
|
|
<div class="hero-content">
|
|
<p class="hero-label" style="animation-delay: 0.2s">New Release — March 2025</p>
|
|
<h1 class="hero-title">
|
|
<span class="highlight">Vessel</span>
|
|
<span class="text-2xl sm:text-3xl" style="color: var(--muted); font-weight: 400; margin-left: 0.5rem;">.3</span>
|
|
</h1>
|
|
<p class="hero-sub">A new chapter. Four songs. One vision. The world is waiting.</p>
|
|
<a href="#tracks" class="hero-cta">Explore the Release</a>
|
|
</div>
|
|
|
|
<div class="hero-scroll" aria-hidden="true">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M12 5v14M5 12l7 7 7-7"/>
|
|
</svg>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Track Listing -->
|
|
<section id="tracks" class="section" aria-label="Track listing">
|
|
<div class="max-w-6xl mx-auto">
|
|
<div class="reveal">
|
|
<p class="section-label">Now Available</p>
|
|
<h2 class="section-title">Track Listing</h2>
|
|
<p class="section-desc">Four compositions exploring the spaces between silence and sound.</p>
|
|
</div>
|
|
|
|
<div class="tracks-grid">
|
|
<!-- Track 1 -->
|
|
<div class="track-card reveal" tabindex="0" role="button" aria-label="Open Track 1: 'Horizon Line'" onclick="addToQueue(1)">
|
|
<div class="track-number">Track 01</div>
|
|
<h3 class="track-title">Horizon Line</h3>
|
|
<p class="track-artist">by Vessel</p>
|
|
<div class="track-duration">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 6v6l4 2"/>
|
|
</svg>
|
|
<span>5:24</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Track 2 -->
|
|
<div class="track-card reveal" tabindex="0" role="button" aria-label="Open Track 2: 'Widow's Bridge'" onclick="addToQueue(2)">
|
|
<div class="track-number">Track 02</div>
|
|
<h3 class="track-title">Widow's Bridge</h3>
|
|
<p class="track-artist">by Vessel</p>
|
|
<div class="track-duration">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 6v6l4 2"/>
|
|
</svg>
|
|
<span>4:18</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Track 3 -->
|
|
<div class="track-card reveal" tabindex="0" role="button" aria-label="Open Track 3: 'Still Life'" onclick="addToQueue(3)">
|
|
<div class="track-number">Track 03</div>
|
|
<h3 class="track-title">Still Life</h3>
|
|
<p class="track-artist">by Vessel</p>
|
|
<div class="track-duration">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 6v6l4 2"/>
|
|
</svg>
|
|
<span>6:07</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Track 4 -->
|
|
<div class="track-card reveal" tabindex="0" role="button" aria-label="Open Track 4: 'Ember Protocol'" onclick="addToQueue(4)">
|
|
<div class="track-number">Track 04</div>
|
|
<h3 class="track-title">Ember Protocol</h3>
|
|
<p class="track-artist">by Vessel</p>
|
|
<div class="track-duration">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="12" height="12">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 6v6l4 2"/>
|
|
</svg>
|
|
<span>4:53</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Artist Profile -->
|
|
<section id="artist" class="section" aria-label="Artist profile">
|
|
<div class="max-w-6xl mx-auto">
|
|
<div class="reveal">
|
|
<p class="section-label">The Artist</p>
|
|
<h2 class="section-title">Meet Vessel</h2>
|
|
<p class="section-desc">A solo project rooted in the tension between minimalism and emotion — a voice that carries the weight of silence.</p>
|
|
</div>
|
|
|
|
<div class="artist-profile reveal">
|
|
<div class="artist-avatar" aria-label="Vessel avatar">
|
|
<img src="https://images.pexels.com/photo/2021/10/10/pexels-photo-2021-10-10-photo-2021-10-10-photo.jpeg?auto=compress&cs=tinysrgb&w=400&h=400&fit=crop" alt="Portrait of Vessel, a musician" loading="lazy">
|
|
</div>
|
|
<div class="artist-info">
|
|
<h3>Vessel</h3>
|
|
<p class="artist-bio">Elena Voss. Singer, songwriter, and sound architect. Based in Portland, Oregon. Producing since 2018.</p>
|
|
<div class="artist-meta">
|
|
<div class="artist-meta-item">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
|
|
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
<path d="M2 17l10 5 10-5"/>
|
|
<path d="M2 12l10 5 10-5"/>
|
|
</svg>
|
|
<strong>5 releases</strong>
|
|
</div>
|
|
<div class="artist-meta-item">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
|
|
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 7.78l1.84 1.84a.7.7 0 0 1 0 1.01l-2.23 2.23a6.6 6.6 0 0 0 9.6 9.6l2.23-2.23a.7.7 0 0 1 1.01 0l1.84 1.84a5.5 5.5 0 0 0 7.78-7.78L13.5 12l2.23-2.23"/>
|
|
</svg>
|
|
<strong>3 years</strong>
|
|
</div>
|
|
<div class="artist-meta-item">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M2 12h20"/>
|
|
</svg>
|
|
<strong>600K+</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="info-grid reveal">
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">17</div>
|
|
<div class="info-label">Songs</div>
|
|
</div>
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">2025</div>
|
|
<div class="info-label">Released</div>
|
|
</div>
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">1.6</div>
|
|
<div class="info-label">Avg Rating</div>
|
|
</div>
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">15</div>
|
|
<div class="info-label">Countries</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Details -->
|
|
<section id="info" class="section" aria-label="Release details">
|
|
<div class="max-w-6xl mx-auto">
|
|
<div class="reveal">
|
|
<p class="section-label">Release Details</p>
|
|
<h2 class="section-title">What's Inside</h2>
|
|
<p class="section-desc">The complete collection — formats, tracks, and everything that comes with the release.</p>
|
|
</div>
|
|
|
|
<div class="info-grid reveal">
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">Digital</div>
|
|
<div class="info-label">Available</div>
|
|
</div>
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
|
<polyline points="7 10 12 15 17 10"/>
|
|
<line x1="12" y1="15" x2="12" y2="3"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">320kbps</div>
|
|
<div class="info-label">Quality</div>
|
|
</div>
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 8v4l3 3"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">March 14</div>
|
|
<div class="info-label">Release Date</div>
|
|
</div>
|
|
<div class="info-item">
|
|
<div class="info-icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22">
|
|
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
|
|
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="info-value">LP + Digital</div>
|
|
<div class="info-label">Formats</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- CTA -->
|
|
<section class="section" aria-label="Call to action">
|
|
<div class="max-w-4xl mx-auto text-center">
|
|
<div class="reveal">
|
|
<p class="section-label">Get Involved</p>
|
|
<h2 class="section-title">Join the Wave</h2>
|
|
<p class="section-desc">Sign up for our newsletter and be among the first to know when new music drops.</p>
|
|
</div>
|
|
<div class="reveal" style="margin-top: 2rem;">
|
|
<form id="newsletter-form" style="display: flex; gap: 0.5rem; max-width: 500px; margin: 0 auto;" onsubmit="handleNewsletter(event)" novalidate>
|
|
<label for="email-input" class="sr-only" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);">Email address</label>
|
|
<input type="email" id="email-input" placeholder="your@email.com" required
|
|
style="flex:1; padding: 0.85rem 1rem; background: var(--card); border: 1px solid var(--border); border-radius: 0; color: var(--fg); font-size: 0.95rem; outline: none; transition: border-color 0.3s;"
|
|
onfocus="this.style.borderColor='var(--accent)'" onblur="this.style.borderColor='var(--border)'"
|
|
aria-label="Email address">
|
|
<button type="submit" class="btn-primary" style="padding: 0.85rem 1.5rem; font-size: 0.9rem;">Subscribe</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Footer -->
|
|
<footer class="site-footer">
|
|
<div class="max-w-6xl mx-auto">
|
|
<div class="footer-grid">
|
|
<div class="footer-brand">
|
|
<h3>Vessel</h3>
|
|
<p>A record label and music project. Created with care.</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold" style="color: var(--fg); margin-bottom: 0.75rem;">Navigation</p>
|
|
<div class="footer-links">
|
|
<a href="#tracks">Tracks</a>
|
|
<a href="#artist">About</a>
|
|
<a href="#info">Details</a>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-semibold" style="color: var(--fg); margin-bottom: 0.75rem;">Contact</p>
|
|
<div class="footer-links">
|
|
<a href="#">hello@vessel.music</a>
|
|
<a href="#">@vessel_music</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="footer-bottom">
|
|
<p>2025 Vessel. All rights reserved.</p>
|
|
<p style="margin-top: 0.25rem;">Crafted with care in the Pacific Northwest</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// --- Loading screen ---
|
|
window.addEventListener('load', () => {
|
|
setTimeout(() => {
|
|
document.getElementById('loader').classList.add('hidden');
|
|
}, 800);
|
|
});
|
|
|
|
// --- Scroll progress bar ---
|
|
const scrollBar = document.getElementById('scroll-progress');
|
|
window.addEventListener('scroll', () => {
|
|
const scrollTop = window.scrollY;
|
|
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
const progress = (scrollTop / docHeight) * 100;
|
|
scrollBar.style.width = progress + '%';
|
|
});
|
|
|
|
// --- Navbar scroll effect ---
|
|
const navbar = document.getElementById('navbar');
|
|
window.addEventListener('scroll', () => {
|
|
if (window.scrollY > 50) {
|
|
navbar.style.borderBottomColor = 'var(--border)';
|
|
navbar.style.background = 'rgba(12,12,12,0.95)';
|
|
} else {
|
|
navbar.style.borderBottomColor = 'transparent';
|
|
navbar.style.background = 'rgba(12,12,12,0.85)';
|
|
}
|
|
});
|
|
|
|
// --- Mobile menu ---
|
|
const mobileBtn = document.getElementById('mobile-menu-btn');
|
|
const mobileMenu = document.getElementById('mobile-menu');
|
|
let menuOpen = false;
|
|
|
|
mobileBtn.addEventListener('click', () => {
|
|
menuOpen = !menuOpen;
|
|
mobileMenu.classList.toggle('hidden', !menuOpen);
|
|
});
|
|
|
|
// Close mobile menu on link click
|
|
mobileMenu.querySelectorAll('a').forEach(a => {
|
|
a.addEventListener('click', () => {
|
|
menuOpen = false;
|
|
mobileMenu.classList.add('hidden');
|
|
});
|
|
});
|
|
|
|
// --- Scroll reveal ---
|
|
const revealElements = document.querySelectorAll('.reveal');
|
|
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('visible');
|
|
}
|
|
});
|
|
}, {
|
|
threshold: 0.1,
|
|
rootMargin: '0px 0px -40px 0px'
|
|
});
|
|
|
|
revealElements.forEach(el => revealObserver.observe(el));
|
|
|
|
// --- Toast ---
|
|
function showToast(message) {
|
|
const toast = document.getElementById('toast');
|
|
const toastMsg = document.getElementById('toast-msg');
|
|
toastMsg.textContent = message;
|
|
toast.classList.add('show');
|
|
|
|
setTimeout(() => {
|
|
toast.classList.remove('show');
|
|
}, 3000);
|
|
}
|
|
|
|
function addToQueue(trackNum) {
|
|
showToast(`"Track ${trackNum}" added to your queue`);
|
|
}
|
|
|
|
function handleNewsletter(e) {
|
|
e.preventDefault();
|
|
const emailInput = document.getElementById('email-input');
|
|
const email = emailInput.value;
|
|
|
|
if (email && email.includes('@') && email.includes('.')) {
|
|
showToast('Welcome to the newsletter. Check your inbox.');
|
|
emailInput.value = '';
|
|
} else {
|
|
showToast('Please enter a valid email address.');
|
|
}
|
|
}
|
|
|
|
// --- Audio waveform animation (visual only) ---
|
|
const waveBars = Array.from({length: 24}, (_, i) => {
|
|
const bar = document.createElement('div');
|
|
bar.className = 'wave-bar';
|
|
bar.style.height = '4px';
|
|
bar.style.background = 'var(--accent)';
|
|
bar.style.borderRadius = '2px';
|
|
bar.style.position = 'absolute';
|
|
bar.style.bottom = '0';
|
|
bar.style.left = `${i * 1.5}%`;
|
|
bar.style.width = '1.5px';
|
|
bar.style.transition = 'height 0.3s ease';
|
|
document.querySelector('.hero-section').appendChild(bar);
|
|
return bar;
|
|
});
|
|
|
|
// Animate wave bars on scroll
|
|
let waveAnimated = false;
|
|
window.addEventListener('scroll', () => {
|
|
if (waveAnimated) return;
|
|
const scrollBottom = window.scrollY > window.innerHeight * 0.7;
|
|
if (scrollBottom && !waveAnimated) {
|
|
waveAnimated = true;
|
|
waveBars.forEach(bar => {
|
|
const height = Math.random() * 120 + 4;
|
|
bar.style.height = height + 'px';
|
|
bar.style.background = Math.random() > 0.5 ? 'var(--accent)' : 'var(--accent-light)';
|
|
});
|
|
setTimeout(() => {
|
|
waveBars.forEach(bar => {
|
|
bar.style.height = '4px';
|
|
bar.style.background = 'var(--accent)';
|
|
});
|
|
waveAnimated = false;
|
|
}, 2000);
|
|
}
|
|
});
|
|
|
|
// --- Parallax effect for hero section ---
|
|
window.addEventListener('scroll', () => {
|
|
const heroContent = document.querySelector('.hero-content');
|
|
const scrollY = window.scrollY;
|
|
if (scrollY < window.innerHeight) {
|
|
heroContent.style.transform = `translateY(${scrollY * 0.15}px)`;
|
|
heroContent.style.opacity = 1 - (scrollY / window.innerHeight) * 0.3;
|
|
}
|
|
});
|
|
|
|
// --- Smooth scroll for anchor links ---
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const target = document.querySelector(anchor.getAttribute('href'));
|
|
if (target) {
|
|
target.scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
});
|
|
});
|
|
|
|
// --- Keyboard accessibility for track cards ---
|
|
document.querySelectorAll('.track-card').forEach(card => {
|
|
card.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
e.preventDefault();
|
|
card.click();
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
<div style="position:fixed;right:12px;bottom:12px;z-index:2147483647;background:rgba(17,24,39,.92);color:#fff;padding:8px 10px;border-radius:10px;font:12px/1.3 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;box-shadow:0 8px 20px rgba(0,0,0,.28)">Generated in 70.17s<br>Model: bloomer010/Ling-3.0-tiny-GGUF:Q4_K_M</div></body>
|
|
</html> |