Files
calvana/pledge-now-pay-later/src/app/for/_components/index.tsx
Omair Saleh e2295020a1 add brand/ assets to repo + BRAND.md as single source of truth
BRAND.md: Complete brand guide with code snippets, color tokens, typography scale,
logo usage rules, DO/DON'T checklist, photography direction, voice & tone.
Every section references its visual asset in brand/.

brand/ folder (52 assets):
- photography/ (20) — landing page photos
- logo/ (6) — lockup, reversed, blue, marks, favicon
- color-palette/ (3) — primary, tints, psychology
- typography/ (3) — specimen, scale, numbers
- moodboard/ (3) — trust, community, editorial
- brand-guide/ (7) — cover through UI patterns
- social-templates/ (4) — OG, Instagram, Story, LinkedIn
- icons/ (6) — pledge, whatsapp, gift-aid, zakat, dashboard, schedule

Also fixed: Nav component still had backdrop-blur-lg (last violation)
2026-03-03 20:31:01 +08:00

118 lines
5.2 KiB
TypeScript

import Link from "next/link"
import Image from "next/image"
/* ── Nav ── */
export function Nav() {
return (
<header className="sticky top-0 z-40 border-b border-gray-200 bg-white">
<div className="max-w-5xl mx-auto flex h-14 items-center justify-between px-6">
<Link href="/" className="flex items-center gap-2.5">
<div className="h-7 w-7 bg-gray-900 flex items-center justify-center">
<span className="text-white text-xs font-black">P</span>
</div>
<span className="font-black text-sm tracking-tight">Pledge Now, Pay Later</span>
</Link>
<div className="flex items-center gap-4">
<Link href="/login" className="text-sm font-medium text-gray-500 hover:text-gray-900 transition-colors">Sign In</Link>
<Link href="/signup" className="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white hover:bg-gray-800 transition-colors">Get Started</Link>
</div>
</div>
</header>
)
}
/* ── Footer ── */
export function Footer({ active }: { active?: string }) {
const links = [
{ href: "/for/charities", label: "Charities" },
{ href: "/for/fundraisers", label: "Fundraisers" },
{ href: "/for/volunteers", label: "Volunteers" },
{ href: "/for/organisations", label: "Organisations" },
]
return (
<footer className="py-10 px-6 border-t border-gray-100">
<div className="max-w-5xl mx-auto flex flex-col md:flex-row items-center justify-between gap-6 text-xs text-gray-400">
<Link href="/" className="flex items-center gap-2">
<div className="h-5 w-5 bg-gray-900 flex items-center justify-center">
<span className="text-white text-[9px] font-black">P</span>
</div>
<span className="text-gray-500">Pledge Now, Pay Later</span>
</Link>
<div className="flex flex-wrap justify-center gap-x-6 gap-y-1">
{links.map((l) => (
<Link
key={l.href}
href={l.href}
className={`hover:text-gray-900 transition-colors ${active && l.href.includes(active) ? "text-gray-900 font-semibold" : ""}`}
>
{l.label}
</Link>
))}
<Link href="/login" className="hover:text-gray-900 transition-colors">Sign In</Link>
</div>
<span>© {new Date().getFullYear()} QuikCue Ltd</span>
</div>
</footer>
)
}
/* ── Bottom CTA ── */
export function BottomCta({ headline, sub }: { headline?: string; sub?: string }) {
return (
<section className="py-24 bg-gray-950 px-6">
<div className="max-w-2xl mx-auto text-center space-y-8">
<h2 className="text-3xl md:text-4xl font-black text-white leading-tight tracking-tight">
{headline || "Every day without this, you're losing pledges."}
</h2>
<p className="text-gray-500 max-w-md mx-auto">
{sub || "Free forever. Two-minute setup. Works tonight."}
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link href="/signup" className="inline-flex items-center justify-center bg-white px-8 py-4 text-base font-bold text-gray-900 hover:bg-gray-100 transition-colors">
Create free account
</Link>
<Link href="/login?demo=1" className="inline-flex items-center justify-center border border-gray-700 px-8 py-4 text-base font-bold text-white hover:bg-white/5 transition-colors">
See live demo
</Link>
</div>
</div>
</section>
)
}
/* ── Landing Image ── */
export function LandingImage({ src, alt, aspect = "video" }: { src: string; alt: string; aspect?: "video" | "square" | "wide" }) {
const aspectClass = aspect === "square" ? "aspect-square" : aspect === "wide" ? "aspect-[2/1]" : "aspect-video"
return (
<div className={`${aspectClass} w-full relative overflow-hidden bg-gray-100`}>
<Image
src={src}
alt={alt}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 50vw"
quality={85}
/>
</div>
)
}
/* ── Image Placeholder (kept as fallback) ── */
export function ImagePlaceholder({ aspect = "video", label }: { aspect?: "video" | "square" | "wide"; label?: string }) {
const aspectClass = aspect === "square" ? "aspect-square" : aspect === "wide" ? "aspect-[2/1]" : "aspect-video"
return (
<div className={`${aspectClass} w-full bg-gray-100 flex items-center justify-center`}>
{label && (
<div className="text-center px-6">
<div className="w-10 h-10 bg-gray-200 mx-auto mb-3 flex items-center justify-center">
<svg className="w-5 h-5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0 0 22.5 18.75V5.25A2.25 2.25 0 0 0 20.25 3H3.75A2.25 2.25 0 0 0 1.5 5.25v13.5A2.25 2.25 0 0 0 3.75 21Z" />
</svg>
</div>
<p className="text-xs text-gray-400">{label}</p>
</div>
)}
</div>
)
}