diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..d198a43 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,581 @@ +/* Zava storefront — global styles */ + +:root { + --color-bg: #fafaf7; + --color-surface: #ffffff; + --color-surface-alt: #f4f1ea; + --color-text: #1a1a1a; + --color-text-muted: #5b5b5b; + --color-border: #e6e2d8; + --color-accent: #c2410c; /* zava terracotta */ + --color-accent-hover: #9a330a; + --color-accent-soft: #fde8d8; + --color-success: #15803d; + + --radius-sm: 6px; + --radius-md: 12px; + --radius-lg: 20px; + + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.08); + + --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, + "Helvetica Neue", Arial, sans-serif; + --font-display: "Playfair Display", Georgia, "Times New Roman", serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace; + + --container-max: 1200px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-bg: #14130f; + --color-surface: #1c1b17; + --color-surface-alt: #23211b; + --color-text: #f5f2ea; + --color-text-muted: #a8a499; + --color-border: #2f2c25; + --color-accent: #f97316; + --color-accent-hover: #fb923c; + --color-accent-soft: #3a1d0a; + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5); + --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.6); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-sans); + font-size: 16px; + line-height: 1.55; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + color: var(--color-accent); + text-decoration: none; + transition: color 0.15s ease; +} +a:hover { + color: var(--color-accent-hover); +} + +img { + max-width: 100%; + display: block; +} + +.container { + width: 100%; + max-width: var(--container-max); + margin: 0 auto; + padding: 0 24px; +} + +/* ---------- Header ---------- */ + +.site-header { + position: sticky; + top: 0; + z-index: 50; + background: rgba(250, 250, 247, 0.85); + backdrop-filter: saturate(180%) blur(14px); + -webkit-backdrop-filter: saturate(180%) blur(14px); + border-bottom: 1px solid var(--color-border); +} + +@media (prefers-color-scheme: dark) { + .site-header { + background: rgba(20, 19, 15, 0.85); + } +} + +.site-header__inner { + display: flex; + align-items: center; + justify-content: space-between; + height: 64px; + gap: 24px; +} + +.brand { + display: flex; + align-items: center; + gap: 10px; + font-family: var(--font-display); + font-size: 1.5rem; + font-weight: 700; + letter-spacing: -0.01em; + color: var(--color-text); +} +.brand:hover { + color: var(--color-text); +} + +.brand__mark { + width: 32px; + height: 32px; + border-radius: 8px; + background: linear-gradient(135deg, var(--color-accent), #f59e0b); + display: grid; + place-items: center; + color: #fff; + font-family: var(--font-sans); + font-weight: 800; + font-size: 1rem; + box-shadow: var(--shadow-sm); +} + +.nav { + display: flex; + gap: 28px; + font-size: 0.95rem; +} +.nav a { + color: var(--color-text-muted); + font-weight: 500; +} +.nav a:hover { + color: var(--color-text); +} + +.header-actions { + display: flex; + align-items: center; + gap: 12px; +} + +.icon-btn { + display: inline-grid; + place-items: center; + width: 40px; + height: 40px; + border-radius: 999px; + background: transparent; + border: 1px solid transparent; + color: var(--color-text); + cursor: pointer; + transition: background 0.15s ease, border-color 0.15s ease; +} +.icon-btn:hover { + background: var(--color-surface-alt); + border-color: var(--color-border); +} + +@media (max-width: 720px) { + .nav { + display: none; + } +} + +/* ---------- Hero ---------- */ + +.hero { + position: relative; + padding: 96px 0 80px; + overflow: hidden; + background: + radial-gradient(circle at 20% 20%, var(--color-accent-soft), transparent 55%), + radial-gradient(circle at 80% 60%, rgba(245, 158, 11, 0.18), transparent 60%), + var(--color-bg); +} + +.hero__inner { + display: grid; + grid-template-columns: 1.2fr 1fr; + gap: 56px; + align-items: center; +} + +@media (max-width: 900px) { + .hero { + padding: 64px 0 56px; + } + .hero__inner { + grid-template-columns: 1fr; + gap: 32px; + } +} + +.hero__eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + font-size: 0.8rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--color-accent); + background: var(--color-accent-soft); + padding: 6px 12px; + border-radius: 999px; + margin-bottom: 20px; +} + +.hero__title { + font-family: var(--font-display); + font-size: clamp(2.5rem, 5.5vw, 4rem); + line-height: 1.05; + letter-spacing: -0.02em; + margin: 0 0 20px; + font-weight: 700; +} + +.hero__title em { + font-style: italic; + color: var(--color-accent); +} + +.hero__subtitle { + font-size: 1.15rem; + color: var(--color-text-muted); + margin: 0 0 32px; + max-width: 56ch; +} + +.hero__cta { + display: flex; + flex-wrap: wrap; + gap: 12px; +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 12px 22px; + font-size: 0.95rem; + font-weight: 600; + border-radius: 999px; + border: 1px solid transparent; + cursor: pointer; + transition: transform 0.1s ease, background 0.15s ease, color 0.15s ease, + border-color 0.15s ease, box-shadow 0.15s ease; + text-decoration: none; +} +.btn:active { + transform: translateY(1px); +} + +.btn--primary { + background: var(--color-accent); + color: #fff; + box-shadow: var(--shadow-sm); +} +.btn--primary:hover { + background: var(--color-accent-hover); + color: #fff; + box-shadow: var(--shadow-md); +} + +.btn--ghost { + background: transparent; + color: var(--color-text); + border-color: var(--color-border); +} +.btn--ghost:hover { + background: var(--color-surface-alt); + color: var(--color-text); +} + +.hero__visual { + position: relative; + aspect-ratio: 4 / 5; + border-radius: var(--radius-lg); + background: + linear-gradient(135deg, #f59e0b 0%, var(--color-accent) 100%); + box-shadow: var(--shadow-lg); + overflow: hidden; +} +.hero__visual::after { + content: ""; + position: absolute; + inset: 0; + background: + radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.35), transparent 50%), + radial-gradient(circle at 70% 80%, rgba(0, 0, 0, 0.25), transparent 60%); +} +.hero__visual-tag { + position: absolute; + bottom: 24px; + left: 24px; + right: 24px; + z-index: 1; + color: #fff; + font-family: var(--font-display); + font-size: 1.5rem; + line-height: 1.2; + text-shadow: 0 2px 12px rgba(0, 0, 0, 0.3); +} + +/* ---------- Section ---------- */ + +.section { + padding: 72px 0; +} + +.section__head { + display: flex; + align-items: end; + justify-content: space-between; + gap: 24px; + margin-bottom: 36px; + flex-wrap: wrap; +} + +.section__title { + font-family: var(--font-display); + font-size: clamp(1.75rem, 3vw, 2.5rem); + font-weight: 700; + letter-spacing: -0.01em; + margin: 0; +} + +.section__subtitle { + color: var(--color-text-muted); + margin: 6px 0 0; + font-size: 1rem; +} + +.section__link { + font-weight: 600; + font-size: 0.95rem; +} + +/* ---------- Product grid ---------- */ + +.product-grid { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); + gap: 24px; +} + +.product-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + overflow: hidden; + display: flex; + flex-direction: column; + transition: transform 0.18s ease, box-shadow 0.18s ease, + border-color 0.18s ease; +} +.product-card:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-md); + border-color: transparent; +} + +.product-card__media { + aspect-ratio: 4 / 3; + background: var(--color-surface-alt); + position: relative; + overflow: hidden; + display: grid; + place-items: center; +} +.product-card__media::before { + content: ""; + position: absolute; + inset: 0; + background: + radial-gradient(circle at 30% 30%, rgba(194, 65, 12, 0.18), transparent 55%), + radial-gradient(circle at 75% 70%, rgba(245, 158, 11, 0.18), transparent 60%); +} +.product-card__initial { + position: relative; + font-family: var(--font-display); + font-size: 3rem; + font-weight: 700; + color: var(--color-accent); + opacity: 0.55; +} + +.product-card__body { + padding: 18px 20px 20px; + display: flex; + flex-direction: column; + gap: 6px; + flex: 1; +} + +.product-card__name { + margin: 0; + font-size: 1.05rem; + font-weight: 600; + letter-spacing: -0.01em; + color: var(--color-text); +} + +.product-card__desc { + margin: 0; + color: var(--color-text-muted); + font-size: 0.9rem; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.product-card__footer { + margin-top: auto; + padding-top: 14px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.product-card__price { + font-family: var(--font-mono); + font-size: 1rem; + font-weight: 600; + color: var(--color-text); +} + +.product-card__add { + font-size: 0.85rem; + font-weight: 600; + color: var(--color-accent); + background: transparent; + border: 1px solid var(--color-border); + padding: 8px 14px; + border-radius: 999px; + cursor: pointer; + transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} +.product-card__add:hover { + background: var(--color-accent); + color: #fff; + border-color: var(--color-accent); +} + +/* ---------- Empty state ---------- */ + +.empty-state { + text-align: center; + padding: 64px 24px; + background: var(--color-surface); + border: 1px dashed var(--color-border); + border-radius: var(--radius-md); + color: var(--color-text-muted); +} + +/* ---------- Feature strip ---------- */ + +.features { + background: var(--color-surface-alt); + border-top: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-border); +} +.features__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 24px; + padding: 36px 0; +} +.feature { + display: flex; + gap: 14px; + align-items: flex-start; +} +.feature__icon { + flex: 0 0 auto; + width: 36px; + height: 36px; + display: grid; + place-items: center; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: 10px; + color: var(--color-accent); + font-size: 1.1rem; +} +.feature__title { + font-weight: 600; + font-size: 0.95rem; + margin: 0 0 2px; +} +.feature__desc { + font-size: 0.85rem; + color: var(--color-text-muted); + margin: 0; +} + +/* ---------- Footer ---------- */ + +.site-footer { + border-top: 1px solid var(--color-border); + background: var(--color-surface); + padding: 48px 0 32px; + margin-top: 48px; +} + +.site-footer__inner { + display: grid; + grid-template-columns: 1.5fr 1fr 1fr 1fr; + gap: 32px; + margin-bottom: 32px; +} +@media (max-width: 800px) { + .site-footer__inner { + grid-template-columns: 1fr 1fr; + } +} + +.site-footer h4 { + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--color-text-muted); + margin: 0 0 12px; +} +.site-footer ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 8px; +} +.site-footer a { + color: var(--color-text); +} +.site-footer a:hover { + color: var(--color-accent); +} + +.site-footer__tagline { + color: var(--color-text-muted); + margin: 8px 0 0; + font-size: 0.9rem; + max-width: 32ch; +} + +.site-footer__bottom { + border-top: 1px solid var(--color-border); + padding-top: 20px; + display: flex; + justify-content: space-between; + gap: 16px; + flex-wrap: wrap; + font-size: 0.85rem; + color: var(--color-text-muted); +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..8d11b68 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,109 @@ +import "./globals.css"; +import type { ReactNode } from "react"; + +export const metadata = { + title: "Zava — Crafted goods for everyday rituals", + description: + "Zava is a curated storefront for thoughtfully designed home goods, apparel, and accessories.", +}; + +export default function RootLayout({ children }: { children: ReactNode }) { + return ( + + +
+
+ + + Zava + + +
+ + + +
+
+
+ + {children} + + + + + ); +} diff --git a/app/page.tsx b/app/page.tsx index 2ba07c4..d132e04 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,19 +1,126 @@ import { db } from "@/lib/db"; export default async function HomePage() { - const products = await db.listProducts({ limit: 12 }); + let products: Awaited> = []; + let dbError = false; + try { + products = await db.listProducts({ limit: 12 }); + } catch { + dbError = true; + } + return ( -
-

Zava — Featured products

- +
+
+
+
+ New season · Spring 2026 +

+ Crafted goods for everyday rituals. +

+

+ Discover small-batch homeware, apparel, and accessories made by + independent makers — designed to be used, loved, and passed on. +

+ +
+ +
+
+ +
+
+
+ +
+

Small-batch

+

From makers we know by name.

+
+
+
+ +
+

Free 30-day returns

+

Take your time deciding.

+
+
+
+ +
+

Carbon-neutral shipping

+

On every order, everywhere.

+
+
+
+ +
+

Lifetime repairs

+

We fix what we sell.

+
+
+
+
+ +
); }