Streaming — Niche / Indie Landing
A moody, editorial landing page for a fictional indie cinema and anime streaming service. Charcoal canvas with amber and magenta accents, a Fraunces serif and Inter sans mix, and a cinephile tone. Features an editorial hero with stats, hand-curated collection cards with live tag filtering, a why-curated manifesto grid, a horizontally scrollable creator spotlight rail, a community signup with email validation, a monthly-yearly pricing toggle, scroll reveals and a toast helper.
MCP
Code
:root {
--bg: #0c0b10;
--surface: #16141d;
--surface-2: #1f1c28;
--ink: #f5f2ee;
--ink-2: #c4bfba;
--muted: #8a8595;
--brand: #f0a020; /* amber accent */
--brand-2: #d94f9c; /* magenta accent */
--accent: #ffffff;
--line: rgba(255,255,255,0.10);
--line-2: rgba(255,255,255,0.18);
--r-sm: 8px;
--r-md: 12px;
--r-lg: 18px;
--shadow: 0 24px 60px -24px rgba(0,0,0,0.8);
--glow: 0 0 0 1px rgba(240,160,32,0.4), 0 18px 50px -18px rgba(240,160,32,0.35);
--serif: "Fraunces", Georgia, "Times New Roman", serif;
--sans: "Inter", system-ui, -apple-system, sans-serif;
}
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
background: var(--bg);
color: var(--ink);
font-family: var(--sans);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
overflow-x: hidden;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.skip-link {
position: absolute; left: 12px; top: -60px; z-index: 200;
background: var(--brand); color: #1a1206; padding: 10px 16px;
border-radius: var(--r-sm); font-weight: 700; transition: top .2s;
}
.skip-link:focus { top: 12px; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 4px; }
/* ---------- buttons ---------- */
.btn {
font-family: var(--sans);
font-weight: 600; font-size: .92rem;
border-radius: 999px; border: 1px solid transparent;
padding: 10px 20px; cursor: pointer;
transition: transform .18s ease, background .2s, border-color .2s, box-shadow .2s;
}
.btn:active { transform: translateY(1px) scale(.99); }
.btn--solid { background: var(--brand); color: #1a1206; }
.btn--solid:hover { box-shadow: var(--glow); transform: translateY(-1px); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-2); }
.btn--ghost:hover { border-color: var(--brand); color: var(--brand); }
.btn--lg { padding: 14px 28px; font-size: 1rem; }
.btn--block { width: 100%; margin-top: auto; }
/* ---------- nav ---------- */
.nav {
position: sticky; top: 0; z-index: 100;
transition: background .3s, border-color .3s, backdrop-filter .3s;
border-bottom: 1px solid transparent;
}
.nav.is-scrolled {
background: rgba(12,11,16,0.82);
backdrop-filter: blur(14px) saturate(140%);
border-bottom-color: var(--line);
}
.nav__inner {
max-width: 1200px; margin: 0 auto; padding: 16px 22px;
display: flex; align-items: center; gap: 28px;
}
.brand { display: inline-flex; align-items: center; gap: 10px; font-weight: 800; letter-spacing: -0.01em; }
.brand__mark {
width: 20px; height: 20px; border-radius: 6px;
background: conic-gradient(from 200deg, var(--brand), var(--brand-2), var(--brand));
box-shadow: var(--glow);
}
.brand__name { font-size: 1.12rem; }
.nav__links { display: flex; gap: 24px; margin-right: auto; }
.nav__links a { color: var(--ink-2); font-size: .92rem; font-weight: 500; transition: color .2s; }
.nav__links a:hover { color: var(--ink); }
.nav__actions { display: flex; gap: 10px; }
.nav__burger {
display: none; flex-direction: column; gap: 5px; background: none; border: 0;
cursor: pointer; padding: 8px;
}
.nav__burger span { width: 24px; height: 2px; background: var(--ink); border-radius: 2px; transition: .25s; }
.nav__burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.mobile-nav {
position: fixed; inset: 64px 0 auto 0; z-index: 99;
background: rgba(12,11,16,0.97); backdrop-filter: blur(16px);
border-bottom: 1px solid var(--line);
display: flex; flex-direction: column; gap: 4px; padding: 16px 22px 24px;
transform: translateY(-120%); transition: transform .32s cubic-bezier(.4,0,.2,1);
}
.mobile-nav.is-open { transform: translateY(0); }
.mobile-nav a { padding: 14px 4px; border-bottom: 1px solid var(--line); color: var(--ink-2); font-weight: 500; }
.mobile-nav .btn { margin-top: 14px; }
/* ---------- hero ---------- */
.hero { position: relative; overflow: hidden; isolation: isolate; }
.hero__bg {
position: absolute; inset: 0; z-index: -2;
background:
radial-gradient(900px 520px at 78% 18%, rgba(217,79,156,0.30), transparent 60%),
radial-gradient(760px 600px at 12% 70%, rgba(240,160,32,0.22), transparent 62%),
linear-gradient(180deg, #141019, #0c0b10 70%);
}
.hero__grain {
position: absolute; inset: 0; z-index: -1; opacity: .5; pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.045'/%3E%3C/svg%3E");
}
.hero__inner {
max-width: 1000px; margin: 0 auto; padding: 96px 22px 88px; text-align: center;
}
.eyebrow {
display: inline-block; font-size: .8rem; letter-spacing: .14em; text-transform: uppercase;
color: var(--brand); font-weight: 600; margin: 0 0 22px;
border: 1px solid var(--line-2); border-radius: 999px; padding: 7px 16px;
background: rgba(240,160,32,0.06);
}
.hero__title {
font-family: var(--serif); font-weight: 500;
font-size: clamp(2.6rem, 8vw, 5.4rem); line-height: 1.02; letter-spacing: -0.02em;
margin: 0 0 24px;
}
.hero__title em { color: var(--brand); font-style: italic; }
.hero__lede {
max-width: 620px; margin: 0 auto 32px; color: var(--ink-2);
font-size: clamp(1rem, 2.4vw, 1.18rem);
}
.hero__cta { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.hero__stats {
list-style: none; margin: 56px 0 0; padding: 0;
display: flex; gap: 40px; justify-content: center; flex-wrap: wrap;
}
.hero__stats strong { display: block; font-family: var(--serif); font-size: 2rem; color: var(--ink); }
.hero__stats span { font-size: .82rem; color: var(--muted); letter-spacing: .03em; }
/* ---------- sections ---------- */
.section { max-width: 1200px; margin: 0 auto; padding: 96px 22px; }
.section__head { max-width: 660px; margin-bottom: 44px; }
.kicker {
font-size: .78rem; letter-spacing: .16em; text-transform: uppercase;
color: var(--brand-2); font-weight: 700; margin: 0 0 14px;
}
.section__title {
font-family: var(--serif); font-weight: 500;
font-size: clamp(1.9rem, 4.6vw, 3rem); letter-spacing: -0.015em; margin: 0 0 16px; line-height: 1.08;
}
.section__sub { color: var(--ink-2); font-size: 1.05rem; margin: 0; max-width: 560px; }
/* ---------- filters ---------- */
.filters { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 30px; }
.chip {
font-family: var(--sans); font-weight: 500; font-size: .88rem;
background: var(--surface); color: var(--ink-2); border: 1px solid var(--line);
padding: 9px 18px; border-radius: 999px; cursor: pointer; transition: .2s;
}
.chip:hover { color: var(--ink); border-color: var(--line-2); }
.chip.is-active { background: var(--brand); color: #1a1206; border-color: var(--brand); }
/* ---------- collection grid ---------- */
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.card {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
overflow: hidden; cursor: pointer;
transition: transform .3s cubic-bezier(.2,.7,.2,1), border-color .3s, box-shadow .3s;
}
.card:hover, .card:focus-visible { transform: translateY(-6px); border-color: var(--line-2); box-shadow: var(--shadow); }
.card.is-hidden { display: none; }
.card__poster {
position: relative; aspect-ratio: 3 / 4; display: flex; align-items: flex-start;
gap: 8px; padding: 12px;
}
.card__poster::after {
content: ""; position: absolute; inset: 0;
background: linear-gradient(180deg, transparent 45%, rgba(0,0,0,0.55));
}
.card__poster--p1 { background: linear-gradient(150deg, #5a2a6b, #1c1230); }
.card__poster--p2 { background: linear-gradient(150deg, #1f4d4a, #0e1f24); }
.card__poster--p3 { background: linear-gradient(150deg, #7a3b1d, #2a1320); }
.card__poster--p4 { background: linear-gradient(150deg, #c25a8a, #2b1730); }
.card__poster--p5 { background: linear-gradient(150deg, #3a3f6b, #15172b); }
.card__poster--p6 { background: linear-gradient(150deg, #8a6a1e, #271c10); }
.badge {
position: relative; z-index: 1; font-size: .68rem; font-weight: 700; letter-spacing: .05em;
padding: 4px 9px; border-radius: 6px; backdrop-filter: blur(4px);
}
.badge--q { background: rgba(0,0,0,0.45); color: var(--ink); border: 1px solid var(--line-2); }
.badge--new { background: var(--brand-2); color: #fff; }
.card__body { padding: 16px 18px 20px; }
.card__body h3 { font-family: var(--serif); font-weight: 500; font-size: 1.22rem; margin: 0 0 6px; }
.card__body p { color: var(--ink-2); font-size: .9rem; margin: 0 0 12px; }
.card__meta { font-size: .76rem; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
/* ---------- curated ---------- */
.curated { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.curated__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.feature {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
padding: 26px 22px; transition: transform .3s, border-color .3s;
}
.feature:hover { transform: translateY(-5px); border-color: var(--brand); }
.feature__num { font-family: var(--serif); font-size: 1.4rem; color: var(--brand); display: block; margin-bottom: 14px; }
.feature h3 { font-size: 1.08rem; margin: 0 0 10px; }
.feature p { color: var(--ink-2); font-size: .92rem; margin: 0; }
/* ---------- creators ---------- */
.creators__rail {
display: grid; grid-auto-flow: column; grid-auto-columns: minmax(280px, 1fr);
gap: 22px; overflow-x: auto; padding: 6px 4px 22px; scroll-snap-type: x mandatory;
scrollbar-width: thin; scrollbar-color: var(--brand) transparent;
}
.creators__rail::-webkit-scrollbar { height: 8px; }
.creators__rail::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 999px; }
.creator {
scroll-snap-align: start; margin: 0; background: var(--surface);
border: 1px solid var(--line); border-radius: var(--r-lg); padding: 24px;
transition: transform .3s, border-color .3s;
}
.creator:hover { transform: translateY(-5px); border-color: var(--line-2); }
.creator__avatar { width: 64px; height: 64px; border-radius: 50%; margin-bottom: 18px; box-shadow: var(--shadow); }
.creator__avatar--a { background: conic-gradient(from 40deg, #d94f9c, #5a2a6b); }
.creator__avatar--b { background: conic-gradient(from 40deg, #f0a020, #7a3b1d); }
.creator__avatar--c { background: conic-gradient(from 40deg, #3a8f86, #1f4d4a); }
.creator__avatar--d { background: conic-gradient(from 40deg, #6a72c2, #3a3f6b); }
.creator h3 { font-family: var(--serif); font-weight: 500; font-size: 1.2rem; margin: 0 0 4px; }
.creator__role { font-size: .8rem; color: var(--brand); margin: 0 0 14px; letter-spacing: .03em; }
.creator__quote { color: var(--ink-2); font-style: italic; font-size: .96rem; margin: 0; }
/* ---------- community ---------- */
.community { }
.community__inner {
background: linear-gradient(135deg, rgba(217,79,156,0.12), rgba(240,160,32,0.10)), var(--surface);
border: 1px solid var(--line-2); border-radius: var(--r-lg);
padding: 48px; display: grid; grid-template-columns: 1.4fr 1fr; gap: 40px; align-items: center;
}
.community__copy .kicker { margin-top: 0; }
.community__signup { display: flex; gap: 10px; margin-top: 26px; flex-wrap: wrap; }
.community__signup input {
flex: 1; min-width: 200px; background: var(--bg); border: 1px solid var(--line-2);
border-radius: 999px; padding: 13px 20px; color: var(--ink); font-family: var(--sans); font-size: .95rem;
}
.community__signup input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(240,160,32,0.2); }
.community__fineprint { color: var(--muted); font-size: .82rem; margin: 14px 0 0; }
.community__fineprint.is-ok { color: var(--brand); }
.community__pills { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.community__pills li {
background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 16px 20px; color: var(--ink-2); font-size: .92rem;
}
.community__pills strong { font-family: var(--serif); font-size: 1.5rem; color: var(--ink); display: block; }
/* ---------- pricing ---------- */
.billing {
display: inline-flex; gap: 4px; background: var(--surface); border: 1px solid var(--line);
border-radius: 999px; padding: 5px; margin-bottom: 36px;
}
.billing__opt {
font-family: var(--sans); font-weight: 600; font-size: .9rem;
background: transparent; border: 0; color: var(--ink-2);
padding: 10px 22px; border-radius: 999px; cursor: pointer; transition: .2s;
}
.billing__opt.is-active { background: var(--brand); color: #1a1206; }
.save { font-size: .72rem; color: var(--brand-2); font-weight: 700; }
.billing__opt.is-active .save { color: #7a1648; }
.plans { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 22px; max-width: 760px; }
.plan {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
padding: 30px; display: flex; flex-direction: column; position: relative; transition: border-color .3s, transform .3s;
}
.plan:hover { transform: translateY(-4px); }
.plan--feature { border-color: var(--brand); box-shadow: var(--glow); background: var(--surface-2); }
.plan__flag {
position: absolute; top: -12px; left: 30px; background: var(--brand); color: #1a1206;
font-size: .72rem; font-weight: 700; letter-spacing: .05em; padding: 5px 12px; border-radius: 999px;
}
.plan__name { font-family: var(--serif); font-weight: 500; font-size: 1.4rem; margin: 0 0 8px; }
.plan__price { display: flex; align-items: baseline; gap: 4px; margin: 0 0 8px; }
.plan__amt { font-family: var(--serif); font-size: 2.6rem; color: var(--ink); }
.plan__per { color: var(--muted); font-size: .9rem; }
.plan__note { color: var(--ink-2); font-size: .92rem; margin: 0 0 20px; }
.plan__list { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 11px; }
.plan__list li { color: var(--ink-2); font-size: .92rem; padding-left: 26px; position: relative; }
.plan__list li::before {
content: ""; position: absolute; left: 0; top: 7px; width: 14px; height: 8px;
border-left: 2px solid var(--brand); border-bottom: 2px solid var(--brand);
transform: rotate(-45deg);
}
/* ---------- cta ---------- */
.cta { max-width: 1200px; margin: 0 auto 96px; padding: 0 22px; }
.cta__inner {
text-align: center; padding: 72px 28px; border-radius: var(--r-lg);
background:
radial-gradient(600px 300px at 50% 0%, rgba(240,160,32,0.20), transparent 60%),
linear-gradient(180deg, var(--surface-2), var(--surface));
border: 1px solid var(--line-2);
}
.cta__inner h2 { font-family: var(--serif); font-weight: 500; font-size: clamp(1.8rem, 5vw, 3rem); margin: 0 0 14px; letter-spacing: -0.015em; }
.cta__inner p { color: var(--ink-2); margin: 0 0 28px; }
/* ---------- footer ---------- */
.footer { border-top: 1px solid var(--line); background: var(--surface); }
.footer__inner {
max-width: 1200px; margin: 0 auto; padding: 56px 22px 36px;
display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 32px;
}
.footer__brand p { color: var(--muted); font-size: .9rem; margin: 16px 0 0; max-width: 280px; }
.footer__brand .brand__mark { margin-bottom: 12px; }
.footer__col h4 { font-size: .82rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink); margin: 0 0 16px; }
.footer__col a { display: block; color: var(--muted); font-size: .92rem; padding: 6px 0; transition: color .2s; }
.footer__col a:hover { color: var(--brand); }
.footer__base {
max-width: 1200px; margin: 0 auto; padding: 22px; border-top: 1px solid var(--line);
color: var(--muted); font-size: .82rem; text-align: center;
}
/* ---------- toast ---------- */
.toast {
position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%) translateY(140%);
background: var(--surface-2); color: var(--ink); border: 1px solid var(--line-2);
padding: 14px 22px; border-radius: var(--r-md); box-shadow: var(--shadow);
font-size: .92rem; z-index: 300; opacity: 0; transition: transform .35s cubic-bezier(.2,.8,.2,1), opacity .35s;
max-width: calc(100% - 32px);
}
.toast.is-show { transform: translateX(-50%) translateY(0); opacity: 1; }
/* ---------- reveal ---------- */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.2,1); }
.reveal.is-in { opacity: 1; transform: none; }
/* ---------- responsive ---------- */
@media (max-width: 920px) {
.nav__links, .nav__actions { display: none; }
.nav__burger { display: flex; }
.grid { grid-template-columns: repeat(2, 1fr); }
.curated__grid { grid-template-columns: repeat(2, 1fr); }
.community__inner { grid-template-columns: 1fr; padding: 36px; }
.footer__inner { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
.nav__inner { padding: 14px 18px; }
.hero__inner { padding: 72px 18px 64px; }
.hero__stats { gap: 26px; }
.section { padding: 68px 18px; }
.grid { grid-template-columns: 1fr; }
.curated__grid { grid-template-columns: 1fr; }
.plans { grid-template-columns: 1fr; }
.footer__inner { grid-template-columns: 1fr; }
.cta__inner { padding: 52px 20px; }
.community__signup .btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
* { scroll-behavior: auto !important; }
.reveal { opacity: 1 !important; transform: none !important; transition: none; }
}(function () {
"use strict";
/* ---------- toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 2600);
}
/* ---------- smooth scroll to target ---------- */
function scrollTo(sel) {
var el = document.querySelector(sel);
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
}
/* ---------- nav scroll state ---------- */
var nav = document.getElementById("nav");
function onScroll() {
if (window.scrollY > 24) nav.classList.add("is-scrolled");
else nav.classList.remove("is-scrolled");
}
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
/* ---------- mobile nav ---------- */
var burger = document.getElementById("burger");
var mobileNav = document.getElementById("mobileNav");
function closeMobile() {
mobileNav.classList.remove("is-open");
mobileNav.setAttribute("aria-hidden", "true");
burger.setAttribute("aria-expanded", "false");
burger.setAttribute("aria-label", "Open menu");
}
burger.addEventListener("click", function () {
var open = mobileNav.classList.toggle("is-open");
mobileNav.setAttribute("aria-hidden", String(!open));
burger.setAttribute("aria-expanded", String(open));
burger.setAttribute("aria-label", open ? "Close menu" : "Open menu");
});
mobileNav.querySelectorAll("a").forEach(function (a) {
a.addEventListener("click", closeMobile);
});
/* ---------- delegated clicks: scroll + toast ---------- */
document.addEventListener("click", function (e) {
var s = e.target.closest("[data-scroll]");
if (s) {
e.preventDefault();
closeMobile();
scrollTo(s.getAttribute("data-scroll"));
return;
}
var t = e.target.closest("[data-toast]");
if (t) {
e.preventDefault();
toast(t.getAttribute("data-toast"));
}
});
/* ---------- collection filters ---------- */
var chips = Array.prototype.slice.call(document.querySelectorAll(".chip"));
var cards = Array.prototype.slice.call(document.querySelectorAll("#collectionGrid .card"));
chips.forEach(function (chip) {
chip.addEventListener("click", function () {
chips.forEach(function (c) {
c.classList.remove("is-active");
c.setAttribute("aria-selected", "false");
});
chip.classList.add("is-active");
chip.setAttribute("aria-selected", "true");
var f = chip.getAttribute("data-filter");
var shown = 0;
cards.forEach(function (card) {
var match = f === "all" || (" " + card.getAttribute("data-tags") + " ").indexOf(" " + f + " ") !== -1;
card.classList.toggle("is-hidden", !match);
if (match) shown++;
});
toast(f === "all" ? "Showing all " + cards.length + " collections" : shown + " collection" + (shown === 1 ? "" : "s") + " in " + chip.textContent.trim());
});
});
/* ---------- card open ---------- */
cards.forEach(function (card) {
function open() {
var title = card.querySelector("h3");
toast("Opening “" + (title ? title.textContent : "collection") + "” — demo only");
}
card.addEventListener("click", open);
card.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); open(); }
});
});
/* ---------- billing toggle ---------- */
var billOpts = Array.prototype.slice.call(document.querySelectorAll(".billing__opt"));
var amts = Array.prototype.slice.call(document.querySelectorAll(".plan__amt"));
var pers = Array.prototype.slice.call(document.querySelectorAll(".plan__per"));
billOpts.forEach(function (opt) {
opt.addEventListener("click", function () {
billOpts.forEach(function (o) { o.classList.remove("is-active"); });
opt.classList.add("is-active");
var yearly = opt.getAttribute("data-bill") === "yearly";
amts.forEach(function (a) {
var v = yearly ? a.getAttribute("data-yearly") : a.getAttribute("data-monthly");
a.textContent = "$" + v;
});
pers.forEach(function (p) { p.textContent = yearly ? "/yr" : "/mo"; });
});
});
/* ---------- community signup ---------- */
var joinBtn = document.getElementById("joinBtn");
var emailInput = document.getElementById("email");
var note = document.getElementById("signupNote");
if (joinBtn) {
joinBtn.addEventListener("click", function () {
var val = (emailInput.value || "").trim();
var ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val);
if (!ok) {
emailInput.focus();
note.textContent = "Please enter a valid email address.";
note.classList.remove("is-ok");
return;
}
note.textContent = "You're on the list — first letter ships Friday.";
note.classList.add("is-ok");
emailInput.value = "";
toast("Welcome to the Driftframe club ✨");
});
emailInput.addEventListener("keydown", function (e) {
if (e.key === "Enter") joinBtn.click();
});
}
/* ---------- scroll reveal ---------- */
var reveals = Array.prototype.slice.call(document.querySelectorAll(".reveal"));
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.classList.add("is-in");
io.unobserve(en.target);
}
});
}, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" });
reveals.forEach(function (r) { io.observe(r); });
} else {
reveals.forEach(function (r) { r.classList.add("is-in"); });
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Driftframe — Curated Cinema & Anime</title>
<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=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="nav" id="nav">
<div class="nav__inner">
<a class="brand" href="#top" aria-label="Driftframe home">
<span class="brand__mark" aria-hidden="true"></span>
<span class="brand__name">Driftframe</span>
</a>
<nav class="nav__links" aria-label="Primary">
<a href="#collections">Collections</a>
<a href="#curated">Why curated</a>
<a href="#creators">Creators</a>
<a href="#community">Community</a>
<a href="#pricing">Pricing</a>
</nav>
<div class="nav__actions">
<button class="btn btn--ghost" type="button" data-toast="Welcome back — sign in coming soon.">Sign in</button>
<button class="btn btn--solid" type="button" data-scroll="#pricing">Start free</button>
</div>
<button class="nav__burger" id="burger" type="button" aria-expanded="false" aria-controls="mobileNav" aria-label="Open menu">
<span></span><span></span><span></span>
</button>
</div>
</header>
<div class="mobile-nav" id="mobileNav" aria-hidden="true">
<a href="#collections">Collections</a>
<a href="#curated">Why curated</a>
<a href="#creators">Creators</a>
<a href="#community">Community</a>
<a href="#pricing">Pricing</a>
<button class="btn btn--solid" type="button" data-scroll="#pricing">Start free</button>
</div>
<main id="main">
<section class="hero" id="top">
<div class="hero__bg" aria-hidden="true"></div>
<div class="hero__grain" aria-hidden="true"></div>
<div class="hero__inner reveal">
<p class="eyebrow">Independent film & anime — handpicked weekly</p>
<h1 class="hero__title">Cinema for the<br /><em>curious few.</em></h1>
<p class="hero__lede">A small, opinionated library of restored classics, festival darlings and rare animation — programmed by humans, not algorithms. No autoplay, no doomscroll. Just the next film worth your evening.</p>
<div class="hero__cta">
<button class="btn btn--solid btn--lg" type="button" data-scroll="#pricing">Start 14-day trial</button>
<button class="btn btn--ghost btn--lg" type="button" data-scroll="#collections">Browse collections</button>
</div>
<ul class="hero__stats">
<li><strong>740+</strong><span>handpicked titles</span></li>
<li><strong>52</strong><span>curators worldwide</span></li>
<li><strong>4K</strong><span>restorations</span></li>
</ul>
</div>
</section>
<section class="section" id="collections" aria-labelledby="collections-h">
<div class="section__head reveal">
<p class="kicker">This week's shelf</p>
<h2 id="collections-h" class="section__title">Collections, programmed by hand</h2>
<p class="section__sub">Every shelf is built by a curator with a point of view — a director retrospective, a mood, a forgotten studio. Filter to find your evening.</p>
</div>
<div class="filters reveal" role="tablist" aria-label="Filter collections">
<button class="chip is-active" role="tab" aria-selected="true" data-filter="all">All</button>
<button class="chip" role="tab" aria-selected="false" data-filter="anime">Anime</button>
<button class="chip" role="tab" aria-selected="false" data-filter="docs">Documentary</button>
<button class="chip" role="tab" aria-selected="false" data-filter="arthouse">Arthouse</button>
<button class="chip" role="tab" aria-selected="false" data-filter="restored">Restored</button>
</div>
<div class="grid" id="collectionGrid">
<article class="card" data-tags="anime restored" tabindex="0">
<div class="card__poster card__poster--p1"><span class="badge badge--q">4K</span><span class="badge badge--new">New</span></div>
<div class="card__body">
<h3>Hand-Drawn Futures</h3>
<p>Cel animation from the studios that refused the machine.</p>
<span class="card__meta">14 films · Anime</span>
</div>
</article>
<article class="card" data-tags="docs" tabindex="0">
<div class="card__poster card__poster--p2"><span class="badge badge--q">HD</span></div>
<div class="card__body">
<h3>The Long Quiet</h3>
<p>Slow-cinema documentaries about landscapes and time.</p>
<span class="card__meta">9 films · Documentary</span>
</div>
</article>
<article class="card" data-tags="arthouse restored" tabindex="0">
<div class="card__poster card__poster--p3"><span class="badge badge--q">4K</span></div>
<div class="card__body">
<h3>Neon & Rain</h3>
<p>City nights from the new wave of Southeast Asian auteurs.</p>
<span class="card__meta">11 films · Arthouse</span>
</div>
</article>
<article class="card" data-tags="anime" tabindex="0">
<div class="card__poster card__poster--p4"><span class="badge badge--new">New</span></div>
<div class="card__body">
<h3>Soft Apocalypse</h3>
<p>Gentle end-of-world animation that lingers for weeks.</p>
<span class="card__meta">7 films · Anime</span>
</div>
</article>
<article class="card" data-tags="docs restored" tabindex="0">
<div class="card__poster card__poster--p5"><span class="badge badge--q">HD</span></div>
<div class="card__body">
<h3>Tape Recovered</h3>
<p>Lost music documentaries, rescued from decaying reels.</p>
<span class="card__meta">12 films · Documentary</span>
</div>
</article>
<article class="card" data-tags="arthouse" tabindex="0">
<div class="card__poster card__poster--p6"><span class="badge badge--q">4K</span><span class="badge badge--new">New</span></div>
<div class="card__body">
<h3>Rooms with No Doors</h3>
<p>Chamber dramas where the whole world is one apartment.</p>
<span class="card__meta">8 films · Arthouse</span>
</div>
</article>
</div>
</section>
<section class="section curated" id="curated" aria-labelledby="curated-h">
<div class="section__head reveal">
<p class="kicker">Why curated</p>
<h2 id="curated-h" class="section__title">The opposite of infinite scroll</h2>
<p class="section__sub">We'd rather show you forty perfect films than forty thousand you'll never watch.</p>
</div>
<div class="curated__grid">
<article class="feature reveal">
<span class="feature__num">01</span>
<h3>Programmed by people</h3>
<p>Real curators — critics, archivists, festival programmers — build every shelf and write the notes that come with it.</p>
</article>
<article class="feature reveal">
<span class="feature__num">02</span>
<h3>No autoplay, no nudge</h3>
<p>Nothing starts without you. No "because you watched", no countdown to the next thing. You choose, deliberately.</p>
</article>
<article class="feature reveal">
<span class="feature__num">03</span>
<h3>Rights paid to makers</h3>
<p>A flat majority of every subscription goes straight to the independent filmmakers and studios we license.</p>
</article>
<article class="feature reveal">
<span class="feature__num">04</span>
<h3>Restored in 4K</h3>
<p>We fund grain-true restorations of films the big platforms forgot, then keep them in the catalogue for good.</p>
</article>
</div>
</section>
<section class="section creators" id="creators" aria-labelledby="creators-h">
<div class="section__head reveal">
<p class="kicker">Creator spotlight</p>
<h2 id="creators-h" class="section__title">The makers behind the frame</h2>
</div>
<div class="creators__rail" id="creatorRail" tabindex="0" aria-label="Featured creators, scrollable">
<figure class="creator reveal">
<div class="creator__avatar creator__avatar--a"></div>
<figcaption>
<h3>Ima Sorano</h3>
<p class="creator__role">Animation director · Tokyo</p>
<p class="creator__quote">"They let the slow scenes breathe. That never happens anywhere else."</p>
</figcaption>
</figure>
<figure class="creator reveal">
<div class="creator__avatar creator__avatar--b"></div>
<figcaption>
<h3>Mara Vey</h3>
<p class="creator__role">Documentarian · Lisbon</p>
<p class="creator__quote">"My festival film found an audience that actually finishes it."</p>
</figcaption>
</figure>
<figure class="creator reveal">
<div class="creator__avatar creator__avatar--c"></div>
<figcaption>
<h3>Dev Okonkwo</h3>
<p class="creator__role">Restoration lead · Lagos</p>
<p class="creator__quote">"We rescued three reels nobody else would pay to scan."</p>
</figcaption>
</figure>
<figure class="creator reveal">
<div class="creator__avatar creator__avatar--d"></div>
<figcaption>
<h3>Lena Frost</h3>
<p class="creator__role">Programmer · Berlin</p>
<p class="creator__quote">"A shelf is an argument. I get to make mine every single week."</p>
</figcaption>
</figure>
</div>
</section>
<section class="section community" id="community" aria-labelledby="community-h">
<div class="community__inner reveal">
<div class="community__copy">
<p class="kicker">Community</p>
<h2 id="community-h" class="section__title">Watch alone. Talk together.</h2>
<p class="section__sub">Every title has a quiet comment thread, a curator's intro, and a monthly live screening with the maker in the room. Bring your takes — it's a cinephile crowd.</p>
<div class="community__signup">
<label class="sr-only" for="email">Email address</label>
<input id="email" type="email" inputmode="email" placeholder="you@example.com" autocomplete="email" />
<button class="btn btn--solid" type="button" id="joinBtn">Join the club</button>
</div>
<p class="community__fineprint" id="signupNote">One letter a week. Spoilers clearly marked. Unsubscribe anytime.</p>
</div>
<ul class="community__pills">
<li><strong>18k</strong> members</li>
<li><strong>2.3k</strong> reviews this month</li>
<li><strong>1</strong> live screening weekly</li>
</ul>
</div>
</section>
<section class="section pricing" id="pricing" aria-labelledby="pricing-h">
<div class="section__head reveal">
<p class="kicker">Pricing</p>
<h2 id="pricing-h" class="section__title">One plan. No tiers, no ads.</h2>
<p class="section__sub">Switch billing and watch the price update. Cancel in two clicks, keep your watch history.</p>
</div>
<div class="billing reveal" role="group" aria-label="Billing period">
<button class="billing__opt is-active" data-bill="monthly" type="button">Monthly</button>
<button class="billing__opt" data-bill="yearly" type="button">Yearly <span class="save">−20%</span></button>
</div>
<div class="plans reveal">
<article class="plan">
<h3 class="plan__name">Drifter</h3>
<p class="plan__price"><span class="plan__amt" data-monthly="6" data-yearly="58">$6</span><span class="plan__per" data-per="mo">/mo</span></p>
<p class="plan__note">The whole curated library, one screen at a time.</p>
<ul class="plan__list">
<li>740+ handpicked titles</li>
<li>HD streaming, one device</li>
<li>Weekly curated shelves</li>
<li>Curator notes & threads</li>
</ul>
<button class="btn btn--ghost btn--block" type="button" data-toast="Drifter trial started — enjoy the films.">Start Drifter</button>
</article>
<article class="plan plan--feature">
<span class="plan__flag">Most loved</span>
<h3 class="plan__name">Cinephile</h3>
<p class="plan__price"><span class="plan__amt" data-monthly="11" data-yearly="106">$11</span><span class="plan__per" data-per="mo">/mo</span></p>
<p class="plan__note">Everything, in 4K, on every screen in the house.</p>
<ul class="plan__list">
<li>Everything in Drifter</li>
<li>4K restorations, 4 devices</li>
<li>Offline downloads</li>
<li>Live screenings with makers</li>
<li>Early access to new shelves</li>
</ul>
<button class="btn btn--solid btn--block" type="button" data-toast="Cinephile trial started — see you at the screening.">Start Cinephile</button>
</article>
</div>
</section>
<section class="cta reveal" aria-labelledby="cta-h">
<div class="cta__inner">
<h2 id="cta-h">Your next favourite film is on the shelf.</h2>
<p>Fourteen days free. No card games, no ads, no algorithm deciding for you.</p>
<button class="btn btn--solid btn--lg" type="button" data-scroll="#pricing">Start watching tonight</button>
</div>
</section>
</main>
<footer class="footer">
<div class="footer__inner">
<div class="footer__brand">
<span class="brand__mark" aria-hidden="true"></span>
<span class="brand__name">Driftframe</span>
<p>Curated cinema & anime for people who still choose what they watch.</p>
</div>
<nav class="footer__col" aria-label="Browse">
<h4>Browse</h4>
<a href="#collections">Collections</a>
<a href="#creators">Creators</a>
<a href="#community">Community</a>
</nav>
<nav class="footer__col" aria-label="Company">
<h4>Studio</h4>
<a href="#curated">Our promise</a>
<a href="#pricing">Pricing</a>
<a href="#top" data-scroll="#top">Back to top</a>
</nav>
<nav class="footer__col" aria-label="Legal">
<h4>Legal</h4>
<a href="#" data-toast="Fictional link — demo only.">Terms</a>
<a href="#" data-toast="Fictional link — demo only.">Privacy</a>
<a href="#" data-toast="Fictional link — demo only.">Licensing</a>
</nav>
</div>
<p class="footer__base">© 2026 Driftframe Collective · A fictional service for demonstration.</p>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Niche / Indie Landing
A full marketing landing page for Driftframe, an imaginary curated streaming service for independent film and anime. It leans into a cinephile, editorial mood: a charcoal canvas, a grainy gradient billboard, and a typographic pairing of the Fraunces serif for headlines against Inter for body copy. Amber and magenta accents replace the usual signature red to signal a smaller, cooler, more handmade brand.
The page is built from a sticky nav that gains a blur backdrop on scroll, an editorial hero with a stat row, a collection grid whose cards filter live by tag (Anime, Documentary, Arthouse, Restored), a four-point “why curated” manifesto, a horizontally scrollable creator-spotlight rail, a community section, and a single-screen pricing block. The CTA and footer close it out, and a mobile burger menu mirrors the nav below 920px.
Interactions are all vanilla JS: tag filtering with a toast count, keyboard-openable cards, a monthly/yearly pricing toggle that rewrites prices and periods, inline email validation on the community signup, an IntersectionObserver scroll-reveal, and a reusable toast(msg) helper. Everything degrades gracefully and respects prefers-reduced-motion.
Illustrative UI only — fictional titles, not a real streaming service.