2 cases built from this template
Same prompt, different [VARIABLES]. Click one to preview it above.About this template
A three-page website for a small family winery that sells its wines online and pours them in its own tasting room. The home page opens on a full-bleed photograph of the vineyard in autumn light, then walks through the estate, three featured wines, a wide barrel-cellar band, the family's story as a vertical timeline that fills in as you scroll, a twelve-month harvest calendar that opens on the current month, and three wine club tiers on a dark cellar background. The wines page lists eight wines with vintage, varietal, alcohol, price and tasting notes that open inside each card, filters by red, white, rosé and sparkling, sorts by price or vintage, and adds bottles, mixed cases or club memberships to a slide-over cart that remembers its contents in the browser and ends in a short checkout and an order confirmation. The visit page books tastings and vineyard walks with an experience picker, a month calendar with closed days and full slots, time chips and a party-size stepper, and shows opening hours, directions and a hand-drawn SVG map of the estate's vine blocks, buildings and walking route. A first-visit age check sits on every page. It suits wineries, cideries with tasting rooms and small farms that sell by mail and host visitors. The look is warm parchment, cellar brown and a single oxblood accent, a classic serif for headings and a clean grotesk for text, and real photographs of vines, grapes, cellars and the hillside. Motion stays slow: images drift, sections fade up, the timeline line grows, the cart slides in, and everything holds still under reduced-motion settings. To adapt it, change the winery name, the family, the region, the grape varieties and the founding year; the prompt asks the builder to rewrite every wine, date, tier and answer to match and to keep all copy in one content file.
The template prompt
The live demo was built from exactly this text — nothing added. The other cases only change the values of the [VARIABLES].
# Family Winery and Vineyard Website
Build this website exactly as described below. Replace the [VARIABLES] with your own values; keep everything else.
## Brief
A three-page website for [BRAND], a family-run winery in [REGION] owned by the [FAMILY] family since [FOUNDED], growing [VARIETIES] on its own hillside. It must look and work like a real estate winery: full-bleed real photographs of the vineyard, grapes, cellar and hillside, photos of the estate's own unlabeled bottles, a wine shop with a slide-over client-side cart and checkout, a tasting and tour booking widget, the estate's story as a timeline, a harvest calendar, wine club tiers, visit information with an SVG-drawn estate map, and an age check on first visit. Pages: index.html (home), wines.html (shop), visit.html (tastings and visit). Everything runs in the browser; nothing is sent anywhere.
- Audience: Wine drinkers within a day's drive of [REGION] planning a weekend visit, and past visitors and club members across the country reordering bottles. Mostly 30–65, curious about how the wine is made, comfortable buying online, and allergic to pretentious wine talk.
- Goal: Sell bottles, mixed cases and club memberships online, and fill tasting-room bookings. Within ten seconds a visitor should know where the estate is, what it grows, what a bottle costs and how to book a tasting; the cart and booking flows must feel finished and trustworthy.
- Tone: Warm, grounded and precise, like a winemaker talking at the barn door. Concrete numbers (acres, cases, months in barrel, prices, hours), plain words for tasting notes, a little dry humor. No wine-snob jargon without explanation, no hype words, no exclamation marks.
## Stack
- Framework: Vite 5 + React 18 + TypeScript
- Styling: Tailwind CSS 3.4
- Libraries: react (MIT), react-dom (MIT), motion (motion.dev, import from 'motion/react') (MIT), lucide-react (ISC), tailwindcss (MIT), postcss (MIT), autoprefixer (MIT), vite (MIT), @vitejs/plugin-react (MIT), typescript (Apache-2.0), @fontsource/cormorant-garamond (OFL-1.1), @fontsource-variable/hanken-grotesk (OFL-1.1)
- Build: `npm run build` → static files in `dist/`. No backend, no server code, no external APIs.
- Setup:
- Scaffold with npm create vite@latest using the react-ts template. Three real HTML pages at the project root: index.html (entry src/main-home.tsx), wines.html (entry src/main-wines.tsx) and visit.html (entry src/main-visit.tsx).
- vite.config.ts: base './', plugins [react()], build { outDir 'dist', sourcemap false, assetsInlineLimit 0, rollupOptions { input { index: resolve(__dirname, 'index.html'), wines: resolve(__dirname, 'wines.html'), visit: resolve(__dirname, 'visit.html') } } }. Do not copy src/ into dist/.
- Tailwind 3.4 through PostCSS (tailwindcss + postcss + autoprefixer), content ['./index.html', './wines.html', './visit.html', './src/**/*.{ts,tsx}']. In tailwind.config.ts add every color under Design to theme.extend.colors with kebab-case keys (parchment, parchment-deep, cream, ink, cellar, cellar-soft, muted, rule, oxblood, oxblood-deep, oxblood-light, olive, oak, sage) and fontFamily display ['Cormorant Garamond', 'Georgia', 'serif'], sans ['Hanken Grotesk Variable', 'system-ui', 'sans-serif']. Set borderRadius DEFAULT to 2px and add maxWidth { container: '1320px' }.
- In src/fonts.ts import '@fontsource/cormorant-garamond/500.css', '@fontsource/cormorant-garamond/600.css', '@fontsource/cormorant-garamond/500-italic.css' and '@fontsource-variable/hanken-grotesk'; import src/fonts.ts and src/index.css from all three entry files.
- File layout: src/content.ts (every string, number, wine, tier, timeline entry, month, experience, hour, FAQ answer, image path and alt text for all three pages, typed), src/lib/brand.ts (brandSlug = [BRAND] lowercased with every run of non-alphanumeric characters replaced by '-', brandInitials = first letter of each word of [BRAND] uppercased, emailDomain = brandSlug without hyphens + '.com'), src/lib/storage.ts (safe localStorage get/set wrapped in try/catch, keys prefixed with brandSlug + ':'), src/lib/useOpenNow.ts, src/lib/useReducedMotion.ts (re-export of Motion's useReducedMotion), src/lib/ics.ts (builds a .ics calendar file as a Blob).
- State: src/store/cart.ts is a tiny external store (useSyncExternalStore) holding cart lines { id, kind: 'wine' | 'case' | 'membership', qty } persisted to localStorage key brandSlug + ':cart', plus drawer open/closed and checkout step. Any page can call addToCart(id, qty) and openCart(). Bookings are saved to brandSlug + ':bookings'; the age check to brandSlug + ':age-ok'.
- Components in src/components/: AgeGate.tsx, Header.tsx, MobileMenu.tsx, CartButton.tsx, CartDrawer.tsx (CartLines.tsx, CheckoutForm.tsx, OrderSuccess.tsx), Reveal.tsx (Motion whileInView wrapper), Eyebrow.tsx, Photo.tsx (image + caption), QtyStepper.tsx, WineCard.tsx, OpenNowPill.tsx, Accordion.tsx, Footer.tsx, CtaBand.tsx; home: Hero.tsx, EstateIntro.tsx, FeaturedWines.tsx, CellarBand.tsx, Timeline.tsx, HarvestCalendar.tsx, WineClub.tsx, VisitTeaser.tsx; wines: WinesMasthead.tsx, FilterBar.tsx, WineGrid.tsx, MixedCases.tsx, ShippingStrip.tsx; visit: VisitHero.tsx, Experiences.tsx, Booking/ (BookingWidget.tsx, ExperiencePicker.tsx, MonthCalendar.tsx, TimeSlots.tsx, GuestStepper.tsx, DetailsFields.tsx, Summary.tsx, BookingSuccess.tsx, availability.ts), HoursDirections.tsx, EstateMap.tsx (inline SVG), Faq.tsx. src/pages/Home.tsx, Wines.tsx and Visit.tsx compose them; every page renders AgeGate, Header, CartDrawer and Footer.
- Before the first build, download every image listed under Assets into public/images/ with curl -L -o using the exact file names given. The build itself never fetches anything.
- public/favicon.svg as described under Assets. All three HTML files: lang en, <meta name='theme-color' content='#F4EEE3'>, <link rel='icon' href='./favicon.svg' type='image/svg+xml'>. Titles: index.html '<title>[BRAND] — Family winery in [REGION]</title>', wines.html '<title>Wines — [BRAND]</title>', visit.html '<title>Visit & tastings — [BRAND]</title>'.
- Write ASSETS.md at the project root as described under Assets.
- dist/ holds the three HTML files, hashed JS/CSS, the woff2 fonts, favicon.svg and the thirteen images. Keep it under 12 MB.
## Variables
- [BRAND] — Winery name (default: "Wexbury Hollow"). Invented estate name. Used in the wordmark, titles, footer, email address (cellar@ + brandSlug without hyphens + .com), localStorage keys and order and booking references (initials, e.g. WH-4821). Never a real winery.
- [FAMILY] — Family name (default: "Marlowe"). The owning family's surname. Drives the timeline, the hero paragraph, the estate intro and the story. All first names are invented to match.
- [REGION] — Wine region (default: "Oregon's Willamette Valley"). Where the estate is. Used in the hero eyebrow, titles, directions, shipping copy and the harvest calendar timing. The road, the town address and the creek stay invented-sounding; only the region and state are real.
- [VARIETIES] — Grape varieties (default: "Pinot Noir, Chardonnay and Pinot Gris"). The grapes the estate grows. Drives the eight wines, the vine blocks on the map, the mixed cases, the tasting experiences and the FAQ. Keep 3 varieties and 8 wines (3 red, 3 white, 1 rosé, 1 sparkling or the closest equivalent).
- [FOUNDED] — Year the family bought the land (default: "1952"). Four-digit year. Drives the hero eyebrow, the wordmark line 'Est. [FOUNDED]' and the first timeline entry; later timeline years are spaced to fit.
- [CREDIT] — keep a small "Template by VibeFather" link to https://vibefather.ai/t/family-winery-and-vineyard-website in the footer (default: yes; delete this line to remove it)
The copy under Pages & Sections is written for the default values. If your values differ, rewrite every headline, paragraph, label and image for them — same length, tone and structure. Layout, colors, type and motion stay as described.
Keep all copy, image paths and links in one content file (for example `src/content.ts`), keyed by section, so the content can be swapped later without touching components.
## Design
### Colors
- Parchment `#F4EEE3` — Page background on all three pages, header background after scroll, cart drawer background.
- Parchment Deep `#EAE1D2` — Alternate section background (Timeline, Booking, Mixed cases), wine card image wells, input fill, hover fill for rows and month cells.
- Cream `#FBF7F0` — Card surfaces (wine cards, experience cards, booking summary), text on photographs and on Cellar backgrounds.
- Ink `#2A211C` — Headlines and body text on light backgrounds, primary outline buttons, icon color.
- Cellar `#1E1714` — Wine Club section, footer, age gate, mobile menu, photo overlays (as rgba(30,23,20,x)).
- Cellar Soft `#2E2420` — Tier cards and hairlines on Cellar backgrounds.
- Muted `#6E6258` — Secondary text, captions, eyebrows, disabled calendar days (at 45% opacity).
- Rule `#D8CCBA` — 1px hairlines, card borders, input borders, map contour lines, timeline base line.
- Oxblood `#6B1F2A` — The one accent: primary buttons, prices, cart badge, selected states, timeline progress line, focus ring, map tasting room and walking route, red wine swatch.
- Oxblood Deep `#521722` — Primary button hover and pressed state.
- Oxblood Light `#C98B8F` — Oxblood replacement for text and lines on Cellar backgrounds (prices, active tier border).
- Olive `#5E6340` — Quiet second color: growth phase in the harvest calendar, vine block hatching on the map, 'Organic' and 'In stock' tags, open-now dot.
- Oak `#8C5E34` — Timeline years, ripening phase in the calendar, oak grove on the map, small numerals. Never for body text.
- Sage `#9FAE9A` — Creek line on the map and the rest-phase bar in the calendar.
### Typography
- Display: H1, H2, H3, wine names, timeline years, prices in large sizes, tasting-note descriptors (italic), the wordmark: Cormorant Garamond (OFL), weights 500/600
- Text and UI: body, eyebrows, buttons, nav, form fields, tables, captions, numbers (font-variant-numeric tabular-nums for prices and hours): Hanken Grotesk (OFL), weights 400/500/600
### Layout & motion
- Spacing: 8px base unit. Container max-width 1320px, centered, side padding 48px desktop, 32px tablet, 20px under 640px. 12-column grid, column gap 24px. Section vertical padding 136px desktop, 96px under 1024px, 80px under 640px. Type scale: H1 clamp(48px, 7vw, 112px) Cormorant Garamond 500, line-height 0.98, letter-spacing -0.01em; H2 clamp(38px, 4.6vw, 72px) Cormorant 500, line-height 1.02; H3 28px Cormorant 600, line-height 1.15; italic phrases in headings use Cormorant 500 italic (marked with *asterisks* in content.ts and rendered as <em>); lead paragraph Hanken 19px / 1.6 Ink at 85% opacity; body Hanken 400 16px / 1.7 (max-width 62ch); eyebrow Hanken 600 12px uppercase letter-spacing 0.18em Muted, preceded by a 24px × 1px Oak line with 12px gap; caption Hanken 13px Muted. Buttons: height 52px, padding 0 28px, Hanken 600 14px uppercase letter-spacing 0.12em. Primary: Oxblood fill, Cream text. Secondary: 1px Ink border, Ink text, transparent (on photos: 1px Cream border, Cream text). Small buttons 40px high, padding 0 18px, 12px text. Inputs: height 52px, 1px Rule border, Cream fill, 16px Hanken, focus border Oxblood. Focus ring everywhere: 2px Oxblood outline with 3px offset (Oxblood Light on dark).
- Radius: 2px on cards, buttons, inputs, chips, photos and the cart drawer edge — nearly square. 999px only for the cart count badge, the open-now dot, the type swatch dots, qty stepper buttons and map stop markers.
- Motion: Easing: --ease-out cubic-bezier(0.22, 0.61, 0.36, 1) for reveals and drawers; --ease-io cubic-bezier(0.65, 0, 0.35, 1) for accordions, month switches and booking steps. Nothing bounces.
- Motion: Reveal: blocks wrapped in <Reveal> start at opacity 0, translateY(20px) and animate to rest over 800ms --ease-out when 15% visible (Motion whileInView, viewport once). Siblings in a list stagger by 80ms (index prop).
- Motion: Hero photos (home and visit): on load the image scales from 1.08 to 1.0 over 2400ms --ease-out; while scrolling, the image translates from 0 to 12% of its height as the hero scrolls out (Motion useScroll target hero, offset ['start start', 'end start'], useTransform), and the headline block fades to opacity 0.2 and moves -40px over the same range. H1 lines rise from translateY(30px) and opacity 0 with 120ms stagger, starting 200ms after load (or after the age gate closes).
- Motion: Image bands (home CellarBand, wines masthead band): parallax, the image inside its overflow-hidden frame moves from -8% to 8% of its height across the frame's scroll progress.
- Motion: Timeline: a 2px Oxblood line over the 1px Rule base line grows with scroll (scaleY 0 → 1, transform-origin top, useScroll on the list with offset ['start 70%', 'end 60%']). Each entry's year dot fills Oxblood when the line reaches it (entry in view at 60%).
- Motion: Wine cards: on hover the bottle photo scales to 1.04 over 700ms --ease-out and the card border turns Ink. 'Add to cart' click: button content crossfades to a Check icon and 'Added' for 1400ms; the header cart badge scales 1 → 1.35 → 1 over 400ms and its number updates.
- Motion: Cart drawer: Cellar overlay fades to 55% opacity over 300ms; the drawer slides in from the right (x 100% → 0) over 420ms --ease-out; closing reverses in 320ms. Checkout steps crossfade with a 16px horizontal slide, 260ms --ease-io (AnimatePresence mode 'wait'). Line removal collapses height over 240ms.
- Motion: Wine grid filtering: cards use Motion layout with AnimatePresence mode 'popLayout'; leaving cards fade and scale to 0.96 over 200ms, remaining cards glide to their new positions over 400ms --ease-io.
- Motion: Accordions (tasting notes, FAQ): height 0 → auto and opacity 0 → 1 over 320ms --ease-io; the Plus icon rotates 45° into an X.
- Motion: Harvest calendar: changing the month crossfades the detail panel (opacity and 12px y) over 300ms --ease-io; the selected month's 2px Oxblood top bar slides between cells with Motion layoutId.
- Motion: Booking: selecting an experience, date or slot animates the selected tile's border and fill over 150ms; the summary price counts to the new total over 400ms; the success state replaces the widget with a fade and a check circle whose stroke draws over 600ms (pathLength 0 → 1).
- Motion: Header: transparent over the photo heroes with Cream text; after 40px of scroll it gets Parchment at 94% opacity, backdrop-filter blur(10px), Ink text and a 1px Rule bottom border, 250ms transition. On wines.html it is solid from the start.
- Motion: Age gate: overlay fades in 400ms on first load; on confirm the card fades and moves up 16px, the overlay fades out over 500ms, then the hero animation starts.
- Motion: Map: when the map enters view, vine blocks fade in with 100ms stagger, then the walking route fades in and its four stop markers pop from scale 0.6 to 1 with 120ms stagger. Hovered or focused blocks rise to full opacity and get a 2px Ink outline over 150ms.
- Motion: Links: .link-draw grows a 1px currentColor underline from 0% to 100% width over 300ms --ease-out on hover and focus-visible.
- Motion: prefers-reduced-motion: reduce — disable the hero scale and parallax, image band parallax, H1 rise, reveals (render at rest), timeline growth (show the full line), grid layout animation, map stagger, count-ups and drawer slide (drawer and overlay appear with a 0ms fade). Color and border hover changes stay. Use CSS @media in index.css plus Motion's useReducedMotion in components.
- Imagery: Real photography only, warm and natural: seven CC0 photos from Wikimedia Commons (golden autumn vineyard above a village, young vines in spring, Pinot Noir clusters on the vine, a vaulted bottle cellar, a hillside vineyard with a small white farm house at golden hour, pruned vines in spring, an 1880s archival vineyard photograph) and six photos made for this template (three unlabeled estate bottles — red, white, rosé — shot identically on an oak plank against limestone, the barrel cellar, the barn tasting room, and a tasting flight on the terrace). No people's faces anywhere, no readable labels, logos or signs. Every photo uses object-fit cover with the object-position given under Assets, square-ish 2px corners, no shadow; photos on Parchment get a 1px Rule outline. Captions sit below in Hanken 13px Muted. Photos under text get a Cellar gradient overlay as specified per section. Drawn in code: the favicon, the wordmark (type only), the estate map, calendar phase bars, type swatch dots, the check circle, dividers. Icons: lucide-react only, stroke width 1.5.
## Pages & Sections
### Home (`index.html`)
1. **Content file and copy rules** — All copy below is written for the default values ([BRAND] = Wexbury Hollow, [FAMILY] = Marlowe, [REGION] = Oregon's Willamette Valley, [VARIETIES] = Pinot Noir, Chardonnay and Pinot Gris, [FOUNDED] = 1952). Put every string, number and list in src/content.ts and render from it; the three pages share one content file. If any variable value differs, rewrite every headline, wine, tasting note, price, timeline entry, harvest month, tier, experience, direction, map label and FAQ answer so it is specific and believable for the new estate, keeping the same structure, counts and lengths. All people, wines, roads, creeks and figures are invented. Estate facts used throughout: address 18450 Larkspur Ridge Road, Amity, OR 97101; phone (503) 555-0172; email cellar@ + emailDomain ([email protected]); 42 acres planted in four blocks; organic since 2011, certified 2014; about 6,000 cases a year; ridge top 620 ft; 50 minutes from downtown Portland. Tasting room hours (time zone America/Los_Angeles): Mon 11:00–17:00, Tue closed, Wed–Thu 11:00–17:00, Fri–Sat 11:00–19:00, Sun 11:00–17:00. Shipping: $15 flat, free on 6 bottles or more, ships Monday to Wednesday, adult signature (21+) required.
Layout: No visual output. content.ts exports typed objects: estate, nav, ageGate, hero, estateIntro, wines (all eight, shared), featuredWineIds, cellarBand, timeline, harvestMonths, club, visitTeaser, cases, shipping, winesFaq, experiences, booking, hours, directions, goodToKnow, mapFeatures, visitFaq, footer, images.
2. **Age gate (all pages)** — Shown on first visit until confirmed; remembered in localStorage brandSlug + ':age-ok' = '1'. Card content: small wordmark '[BRAND]' (Cormorant 600, uppercase, letter-spacing 0.18em, 16px), a 40px Oak hairline, H2-size question 'Are you 21 or older?' (Cormorant 500, 44px), text 'You must be of legal drinking age to enter. We ask once and remember on this device.' Two buttons side by side: primary 'Yes, I'm 21 or older' and secondary 'Not yet'. 'Not yet' replaces the buttons with 'Come back when you're 21. Our grape juice is pretty good, though.' and a text link 'I pressed the wrong button' that restores the buttons. Below, caption 'By entering you agree to enjoy responsibly.'
Layout: Fixed full-viewport overlay, Cellar at 82% opacity over the page (the hero stays visible behind it), z-index above everything. Centered card 480px wide (calc(100% - 40px) on mobile), Cream background, padding 48px (32px mobile), text centered, buttons 52px high, stacked full-width under 480px. Page scroll locked while open. Focus is trapped in the card and starts on the primary button; Escape does nothing. role 'dialog', aria-modal true, aria-labelledby on the question.
Motion: Overlay fades in 400ms; on confirm the card moves up 16px and fades, overlay fades out 500ms. Instant under reduced motion.
3. **Header (all pages)** — Left: wordmark '[BRAND]' (Cormorant 600, 20px, uppercase, letter-spacing 0.2em) with a second line 'Est. [FOUNDED]' (Hanken 500, 10px uppercase, letter-spacing 0.24em), linking to ./index.html. Center nav (Hanken 500 14px): 'Wines' → ./wines.html, 'Visit' → ./visit.html, 'Our story' → ./index.html#story, 'Wine club' → ./index.html#club. Current page link has a 1px underline. Right: small secondary button 'Book a tasting' → ./visit.html#book (hidden under 1024px) and the cart button: Lucide ShoppingBag 22px with a count badge (18px Oxblood circle, Cream 11px Hanken 600 number, hidden when 0), aria-label 'Cart, n items', opens the cart drawer.
Layout: Fixed at top, height 80px (64px under 768px), container inside, three-part flex (wordmark left, nav centered absolutely, actions right). Under 1024px the nav hides and a Lucide Menu button sits left of the cart; it opens a full-screen Cellar menu with the four links in Cormorant 500 40px Cream stacked with 24px gaps, the 'Book a tasting' primary button, the address and hours today in Hanken 14px Cream at 70%, and an X close button top right. Menu traps focus, closes on Escape and on link click.
Motion: Transparent-to-solid transition as in Design motion. Mobile menu fades in 250ms with links rising 12px at 60ms stagger.
4. **Hero** — Background photo hero-vineyard.jpg. Eyebrow (Cream, line in Cream at 60%): 'Family estate · [REGION] · Since [FOUNDED]'. H1 in two lines: 'Grown on one hillside,' / '*bottled a hundred steps away.*' Lead (Cream at 88%, max-width 560px): 'The Marlowe family has farmed Larkspur Ridge since 1952. We grow Pinot Noir, Chardonnay and Pinot Gris on 42 organic acres, make every wine in a cellar dug into the hill, and pour them in the old hay barn six days a week. We close on Tuesdays to walk the rows.' Buttons: primary 'Shop the wines' → ./wines.html (with Lucide ArrowRight 16px), secondary on-photo 'Book a tasting' → ./visit.html#book. Bottom ledger of four items, each a big value (Cormorant 500 32px Cream) over a label (Hanken 12px uppercase letter-spacing 0.14em Cream at 70%): '42 acres' / 'Organic since 2011'; '8 wines' / 'All estate grown'; '6 days' / 'Tastings, closed Tue'; '$15' / 'Shipping, free on 6+'.
Layout: Height 100svh, min-height 680px, max-height 1000px. Image object-fit cover, object-position 50% 62%. Overlay linear-gradient(180deg, rgba(30,23,20,0.45) 0%, rgba(30,23,20,0.10) 35%, rgba(30,23,20,0.25) 60%, rgba(30,23,20,0.78) 100%). Content block anchored bottom-left inside the container, 136px above the ledger, max-width 820px. Ledger: absolute bottom 0, full container width, a 1px Cream/25% top border, 4 equal columns with 1px Cream/25% vertical dividers, padding 24px 0 32px. Under 768px: H1 at 48px, ledger becomes a 2×2 grid, buttons stack full-width, content 32px above the ledger.
Motion: Load scale, scroll parallax, headline fade and H1 line rise as in Design motion. Ledger items fade up with 100ms stagger after the H1.
5. **Estate intro** — id 'estate'. Eyebrow 'The estate'. H2: 'Forty-two acres, *farmed by the people who drink the wine.*' Paragraph 1: 'Walter and Ruth Marlowe bought a hazelnut orchard and sixty acres of sheep pasture on Larkspur Ridge in 1952. Their son planted the first Pinot Noir in 1968, on its own roots, by hand. Today their grandchildren Theo and Ines run the place, and the vines on the south slope are older than both of them.' Paragraph 2: 'We farm organically, keep yields low, pick by hand at dawn and make about 6,000 cases a year. Nothing is bought in: every grape in every bottle grew within sight of the tasting room.' Facts row of three: '1968' / 'First vines planted'; '620 ft' / 'Top of the ridge'; '6,000' / 'Cases a year'. Link 'Read our story' with ArrowRight → #story. Photo vines-spring.jpg with caption 'The south slope in May, two weeks after budbreak.'
Layout: Parchment background. 12-column grid: photo in columns 1–6 (aspect 4/5, object-position 50% 55%), text in columns 8–12 vertically centered. Facts row: three columns separated by 1px Rule vertical lines, value Cormorant 500 44px Ink, label Hanken 13px Muted, 40px above and below the row with 1px Rule lines. Under 1024px stack: text first, photo after at aspect 4/3.
Motion: Photo reveal with a clip-path from inset(0 0 100% 0) to inset(0) over 1100ms --ease-out; text blocks reveal with stagger.
6. **Featured wines** — Eyebrow 'From the cellar'. H2 'Three bottles to start with.' Right of the heading: text link 'See all eight wines' → ./wines.html. Three WineCards for the ids hillside-pinot, estate-chardonnay and rose (data in the Wines page 'Wine grid' section). Below the grid a centered caption: 'Every wine ships in 2–5 days. Free shipping on 6 bottles or more.'
Layout: Parchment background. Heading row: flex space-between, baseline aligned, 56px below. Grid 3 columns gap 24px; under 1024px 2 columns, under 640px 1 column. WineCard exactly as defined on the Wines page but without the tasting-notes accordion.
Motion: Cards reveal with 80ms stagger; hover and add-to-cart behavior as in Design motion.
7. **Cellar band** — Wide photo barrel-room.webp. Overlaid bottom-left: eyebrow (Cream) 'The cellar', Cormorant 500 italic 40px Cream line 'Dug into the hill in 1994. Fifty-eight degrees, all year, without a single air conditioner.' To the right three overlaid stats (value Cormorant 500 40px Cream, label Hanken 12px uppercase Cream at 70%): '212' / 'French oak barrels'; '18 months' / 'For the Founder's Block'; '58°F' / 'Year-round, by nature'. Caption below the band: 'The barrel cellar, lit for racking day.'
Layout: Full-bleed (no container) frame, aspect 21/9 desktop, 4/5 under 768px (object-position 50% 50%), overflow hidden. Overlay linear-gradient(0deg, rgba(30,23,20,0.82) 0%, rgba(30,23,20,0.2) 55%, rgba(30,23,20,0) 100%). Text block inside the container, 56px from the bottom; stats in a row on the right on desktop, below the line on mobile (stacked, 16px gaps). Caption inside the container below the frame, 12px top margin.
Motion: Image parallax as in Design motion; stats count up from 0 over 1400ms easeOutCubic when 40% visible (the '°F' and ' months' suffixes stay static).
8. **Story timeline** — id 'story'. Eyebrow 'Our story'. H2 'Three generations *on one ridge.*' Paragraph: 'The short version: a sheep farm became a hazelnut orchard became a vineyard, and every generation kept the barn.' Archive photo archive-vineyard.jpg with caption 'Head-trained vines like the first ones Walter planted. Archival photograph, 1880s, public domain.' Six entries (year, title, text): 1952 — 'Sixty acres and a hay barn' — 'Walter and Ruth Marlowe buy pasture and a hazelnut orchard on Larkspur Ridge for $9,000. The barn is already thirty years old.'; 1968 — 'The first four acres' — 'Their son Arthur plants Pinot Noir on its own roots on the south slope, one cutting at a time. Neighbors tell him nothing will ripen up there.'; 1979 — 'The first vintage' — '310 cases of Pinot Noir, bottled by hand in the barn and sold out of the back of a pickup at the Saturday market.'; 1994 — 'A cellar in the hill' — 'Joan Marlowe takes over the winemaking and digs the barrel cellar into the ridge: 58°F year-round, no compressor needed.'; 2011 — 'Organic, then certified' — 'No herbicides, cover crops between every row, and forty sheep that mow the vineyard every winter. Certified organic in 2014.'; 2023 — 'The third generation' — 'Theo and Ines Marlowe rebuild the barn into the tasting room with its own timbers and open it six days a week.'
Layout: Parchment Deep background. 12-column grid. Left: columns 1–5, position sticky top 120px: eyebrow, H2, paragraph, then the archive photo frame (aspect 4/3, overflow hidden, img object-fit cover with transform scale(1.3) and transform-origin 50% 45% so the photograph's paper mount and handwritten caption are cropped away, filter sepia(0.25)), caption. Right: columns 7–12, an ordered list with a 1px Rule vertical line at left 7px and the Oxblood progress line over it; each entry has padding-left 48px and 72px bottom gap, a 15px circle dot at left 0 (Parchment Deep fill, 1px Oak border; filled Oxblood when reached), year in Cormorant 500 56px Oak line-height 1, title H3 Ink, text 16px max 46ch. Under 1024px the left column is not sticky and sits above the list; the photo is 100% wide.
Motion: Timeline line growth and dot fill as in Design motion; each entry reveals with Reveal.
9. **Harvest calendar** — id 'calendar'. Eyebrow 'The vineyard year'. H2 'What's happening *on the hill this month.*' Legend (four swatches 12×6px with labels Hanken 13px): Rest (Sage), Growth (Olive), Ripening (Oak), Harvest (Oxblood). Twelve months (abbr, phase, title, text, ifYouVisit): Jan — Rest — 'Pruning begins' — 'We cut each vine back to two canes by hand. It takes the whole crew five weeks.' — 'Bring boots; the rows are muddy and the barn fire is lit.'; Feb — Rest — 'Pruning and tying' — 'Canes get bent and tied to the fruiting wire. The sheep finish their last pass.' — 'Library tastings only on weekends; we're out in the rows.'; Mar — Rest — 'Bleeding vines' — 'Sap rises and pruning cuts drip. The first club shipment goes out.' — 'Club pickup party, second Saturday.'; Apr — Growth — 'Budbreak' — 'Tiny green shoots open on the south slope first. Frost nights mean someone sleeps in the barn.' — 'Vineyard walks resume.'; May — Growth — 'Shoot thinning' — 'We remove the weaker shoots so each vine carries less and ripens better.' — 'The rosé from last year is almost gone. Grab it.'; Jun — Growth — 'Flowering' — 'Grape flowers are tiny and smell faintly of honey. A cold rain now decides the size of the harvest.' — 'Friday and Saturday tastings run until 19:00.'; Jul — Growth — 'Canopy work' — 'Leaf pulling on the morning side so clusters get light without sunburn.' — 'Terrace season. Book the seated tasting early.'; Aug — Ripening — 'Véraison' — 'Green berries turn purple over about two weeks. We start tasting grapes every morning.' — 'Ask for a berry on the vineyard walk.'; Sep — Harvest — 'Harvest' — 'Picking by hand at dawn, Chardonnay and Pinot Gris first. The crush pad runs until dark.' — 'Expect tractors on the drive and the smell of fermenting fruit.'; Oct — Harvest — 'Last picks and pressing' — 'The Founder's Block comes in last. New wine goes to barrel; the second club shipment goes out.' — 'Harvest dinner for Library members, third Saturday.'; Nov — Rest — 'Leaf fall' — 'The vines turn gold and drop their leaves. Cover crops go in between the rows.' — 'Holiday orders ship until December 14.'; Dec — Rest — 'Quiet cellar' — 'Wine rests in barrel. We top up barrels weekly and taste the new vintage.' — 'Open daily except Tuesday and December 24–26.' Detail panel side photo grapes-pinot.jpg, caption 'Pinot Noir in late August, halfway through véraison.'
Layout: Parchment background. Header row: heading left, legend right (wraps under the heading under 1024px). Month strip: a role 'tablist' of 12 buttons in a 12-column grid with 1px Rule borders between cells (6 columns × 2 rows under 1024px, 4 × 3 under 640px). Each cell 104px high, padding 16px: month abbr Hanken 600 13px uppercase, a 6px phase bar in the phase color full cell width, phase name Hanken 12px Muted. Selected cell: Cream fill, a 2px Oxblood bar on the top edge (shared layoutId), aria-selected true. Default selection is the current month from new Date().getMonth(), labelled with a small 'Now' tag (Hanken 600 10px uppercase Oxblood). Arrow keys move between months. Detail panel (role 'tabpanel') below with 48px top gap: grid columns 1–7 text (month full name as eyebrow, title H3 at 36px, text 18px, then 'If you visit:' in Hanken 600 with the ifYouVisit text), columns 8–12 the photo at aspect 3/2, object-position 50% 60%.
Motion: Selected-bar glide and panel crossfade as in Design motion.
10. **Wine club** — id 'club'. Eyebrow (Cream at 70%) 'Wine club'. H2 (Cream) 'Join the *cellar list.*' Paragraph (Cream at 80%): 'Club members get our wines first, at a better price, picked by the people who made them. Shipments go out in March, June and October. Skip any shipment, or cancel with one email.' Photo cellar-tunnel.jpg, caption (Cream at 60%) 'Bottles resting in the old cellar before release.' Three tiers (name, bottles, shipments, price, perks): 'Hillside' — '3 bottles' — '3 shipments a year' — 'from $99 a shipment' — perks '10% off every order', 'Free tastings for 2 every visit', 'Members-only rosé allocation'; 'Cellar' (badge 'Most chosen') — '6 bottles' — '3 shipments a year' — 'from $189 a shipment' — perks '15% off every order', 'Free tastings for 4 every visit', 'Free shipping on every order', 'First access to Founder's Block'; 'Library' — '12 bottles' — '2 shipments a year' — 'from $420 a shipment' — perks '20% off every order', 'One seated Cellar Library tasting a year', 'Two library releases a year', 'A seat at the October harvest dinner'. Each tier button 'Join [tier name]' adds a membership line (id club-hillside, club-cellar, club-library; price 99, 189, 420; qty fixed 1, only one membership in the cart at a time — a new one replaces the old) and opens the cart. Fine print below (Cream at 55%, 13px): 'Memberships renew until you cancel. Prices are before tax; shipping included for Cellar and Library.'
Layout: Cellar background, Cream text. Top: 12-column grid, text in columns 1–6, photo in columns 8–12 (aspect 4/3, object-position 50% 45%, 1px Cellar Soft outline). 72px below: three tier cards in a 3-column grid gap 24px (1 column under 1024px). Card: Cellar Soft background, 1px rgba(251,247,240,0.12) border, padding 40px; name Cormorant 600 36px Cream; bottles and shipments Hanken 14px Cream at 70%; price Cormorant 500 32px Oxblood Light; 1px hairline; perk list with Lucide Check 16px Oxblood Light, Hanken 15px, 12px gaps; button full width at the bottom (primary Oxblood on the Cellar tier, on-dark secondary for the other two). The 'Most chosen' tier has a 1px Oxblood Light border and the badge (Hanken 600 11px uppercase, Oxblood Light text, 1px Oxblood Light border, padding 4px 10px) top right.
Motion: Cards reveal with stagger; card border brightens to rgba(251,247,240,0.3) on hover over 200ms.
11. **Visit teaser** — Eyebrow 'Visit'. H2 'Taste it *where it grows.*' Paragraph: 'The tasting room is the 1920s barn at the top of the drive. Pour five wines at the bar, walk the south slope with someone from the vineyard crew, or sit down with the library wines and a cheese board.' Below, OpenNowPill and a compact hours list (7 rows, day left, hours right, tabular numbers, today's row in Hanken 600 with a 2px Oxblood left border). Buttons: primary 'Book a tasting' → ./visit.html#book, text link 'Directions and map' → ./visit.html#map. Photo tasting-room.webp, caption 'The bar in the old barn, ten minutes before opening.'
Layout: Parchment background. 12-column grid: photo columns 1–7 (aspect 4/3, object-position 50% 50%), text columns 9–12. Hours list max-width 340px, rows 36px with 1px Rule separators. Stack under 1024px, text first.
Motion: Photo clip-path reveal like Estate intro; text reveal with stagger.
12. **Footer (all pages)** — Top row: wordmark '[BRAND]' (Cormorant 600 28px uppercase letter-spacing 0.2em Cream) with 'Family estate in [REGION] since [FOUNDED]' (Hanken 14px Cream at 65%). Four columns of links (heading Hanken 600 12px uppercase letter-spacing 0.16em Cream at 55%, links Hanken 15px Cream with link-draw): 'Shop' — Wines (./wines.html), Mixed cases (./wines.html#cases), Wine club (./index.html#club); 'Visit' — Book a tasting (./visit.html#book), Hours & directions (./visit.html#hours), Estate map (./visit.html#map); 'Estate' — Our story (./index.html#story), Harvest calendar (./index.html#calendar), FAQ (./visit.html#faq); 'Find us' — the address on two lines, the phone as a tel: link, the email as a mailto: link, and OpenNowPill (on-dark). Bottom bar: 'Please enjoy responsibly. You must be 21 or older to purchase or taste.' left; '© ' + current year + ' [BRAND]' right; the optional credit link from the Credit section sits after it.
Layout: Cellar background. Container, padding 96px 0 40px. Top row wordmark left. 64px below: 4 equal columns (2 under 1024px, 1 under 640px) gap 32px. Bottom bar 64px below with a 1px rgba(251,247,240,0.12) top border, padding-top 24px, Hanken 13px Cream at 55%, flex space-between, stacked under 768px.
Motion: None.
13. **Cart drawer (all pages)** — Three steps in one drawer. Step 'cart': heading 'Your cart' with item count, X close button. Free-shipping meter: when bottles < 6 'Add n more bottles for free shipping' over a 4px Rule track with an Oxblood fill (bottles/6), when ≥ 6 'Free shipping unlocked' with Lucide Truck. Lines: thumbnail (56×72, object-fit cover, Parchment Deep well), name (Cormorant 600 20px), meta (vintage · type, or '6 bottles' / '12 bottles' for cases, or '3 shipments a year' for memberships, Hanken 13px Muted), QtyStepper (wines and cases, 1–24; memberships show 'Membership' tag instead), line total (Hanken 600, tabular), remove button (Lucide X 16px, aria-label 'Remove [name]'). Membership lines use the Cellar-coloured thumbnail square with a Lucide Wine icon. Summary: Subtotal; Shipping ('Free' when bottles ≥ 6 or the cart holds a Cellar or Library membership, '$15.00' otherwise, '—' when the cart is empty); Total in Cormorant 500 32px. Bottles count = wine qty + 6 × qty of Hillside Six + 12 × qty of Ridge Dozen. Primary button 'Checkout' and caption 'Ships Mon–Wed. Adult signature (21+) required.' Empty state: Lucide ShoppingBag 32px Muted, 'Your cart is empty.', text link 'Browse the wines' → ./wines.html. Step 'checkout': back link 'Back to cart' (ChevronLeft), heading 'Where should we ship?', fields Full name, Email, Street address, City, State (2-letter, uppercase), ZIP (5 digits), checkbox 'I am 21 or older and an adult will sign for this delivery.' (required), the order total, primary button 'Place order'. Inline validation on blur and on submit: 'Please enter your name.', 'Please enter a valid email.', 'Please enter a 5-digit ZIP code.', 'Please confirm you are 21 or older.' (role alert, Oxblood 13px). The form calls preventDefault and sends nothing. Step 'success': drawn check circle, heading 'Order ' + brandInitials + '-' + 4 random digits + ' is reserved.', text 'Thank you, [first name]. Nothing has been charged. We'll confirm by email before anything ships, usually on the next Monday.', summary of items, button 'Keep browsing' (closes the drawer). Placing the order clears the cart.
Layout: Fixed right drawer, width 440px (100vw under 520px), full height, Parchment background, 1px Rule left border, flex column: header 72px with 1px Rule bottom border, scrollable body padding 24px, sticky footer summary with 1px Rule top border and padding 24px. Lines are 96px rows separated by 1px Rule. Overlay Cellar at 55% covers the page; click on overlay or Escape closes. Focus trapped while open, returns to the cart button on close. role 'dialog', aria-modal true, aria-label 'Cart'.
Motion: Drawer slide, overlay fade, step transitions and line collapse as in Design motion.
### Wines (`wines.html`)
1. **Masthead** — Header solid from the top. Eyebrow 'The wines'. H1 'Eight wines, *every grape from the ridge.*' Lead: 'Pinot Noir, Chardonnay and Pinot Gris from our four blocks. Order by the bottle or the case; we ship Monday to Wednesday so nothing sits in a hot truck over the weekend.' Right of the lead, three small facts (Hanken 13px, Lucide icons 16px Olive): Leaf 'Certified organic', Truck 'Free shipping on 6+', Wine 'Members save 10–20%'. Below, an image band barrel-room.webp with caption 'Founder's Block Pinot Noir, month eleven of eighteen.'
Layout: Parchment background, padding-top 176px (80px header + 96px). Heading block columns 1–8, facts list columns 10–12 aligned to the bottom of the lead. Image band 56px below: inside the container, aspect 3/1 (4/3 under 768px), object-position 50% 55%, overflow hidden, 1px Rule outline.
Motion: H1 line rise on load, band parallax as in Design motion.
2. **Filter and sort bar** — Filter chips (role 'radiogroup', aria-label 'Filter by type'), each with a type swatch dot and a count: 'All 8', 'Red 3', 'White 3', 'Rosé 1', 'Sparkling 1'. Sort select (native <select>, label 'Sort'): 'Featured' (content order), 'Price: low to high', 'Price: high to low', 'Vintage: newest' (NV sorts last). Result line: 'Showing n wines'. Filter and sort persist in the URL hash (#type=red&sort=price-asc) so the state survives reload; unknown values fall back to All / Featured.
Layout: Sticky at top 80px (64px under 768px), Parchment at 94% with backdrop blur(10px), 1px Rule top and bottom borders, height 68px, container inside: chips left (40px high, 1px Rule border, padding 0 16px, Hanken 500 14px; selected chip Ink fill and Cream text), sort and result count right. Under 768px the chips row scrolls horizontally inside itself (overflow-x auto, no visible scrollbar, scroll-snap) and the sort select moves to a second 52px row with the count.
Motion: Chip fill change 150ms.
3. **Wine grid** — Eight wines (id, vintage, name, type, varietal, abv, price, descriptors, blurb, nose, palate, finish, pairs, cellar, badge, image): 1. hillside-pinot — 2023 — 'Hillside Pinot Noir' — red — 'Pinot Noir, all four blocks' — 13.1% — $38 — 'Bing cherry · forest floor · clove' — 'Our everyday Pinot from every block on the ridge. Bright, a little savory, made to be opened on a weeknight.' — 'Bing cherry, raspberry leaf, a pinch of clove.' — 'Juicy red fruit, fine tannins, cool acidity.' — 'Medium, with a hint of forest floor.' — 'Roast chicken, mushroom risotto, grilled salmon.' — 'Drink now–2029' — none — bottle-red. 2. founders-block — 2022 — 'Founder's Block Pinot Noir' — red — 'Pinot Noir, own-rooted 1968 vines' — 13.6% — $64 — 'black cherry · cocoa nib · violet' — 'From the four acres Arthur planted by hand. Eighteen months in French oak, a third of it new.' — 'Black cherry, crushed violet, cedar.' — 'Dense and silky, cocoa nib, dark plum.' — 'Long, with fine-grained tannin.' — 'Duck breast, lamb chops, aged Gouda.' — 'Best 2025–2034' — 'Reserve' — bottle-red. 3. library-pinot — 2019 — 'Library Pinot Noir' — red — 'Pinot Noir, south slope' — 13.4% — $88 — 'dried cherry · tobacco leaf · rose hip' — 'Held back in our cellar for five years and released once. 140 cases.' — 'Dried cherry, rose hip, tobacco leaf.' — 'Mellow and savory, soft tannins, earthy.' — 'Long and gently spiced.' — 'Braised short rib, wild mushrooms, truffle pasta.' — 'Drink now–2030' — 'Library · 140 cases' — bottle-red. 4. estate-chardonnay — 2023 — 'Estate Chardonnay' — white — 'Chardonnay, Ridge Block' — 12.9% — $34 — 'Meyer lemon · hazelnut · wet stone' — 'Whole-cluster pressed and aged ten months in old barrels. Clean, citrusy and a little nutty, like the orchard it replaced.' — 'Meyer lemon, white flowers, hazelnut.' — 'Crisp and round, lemon curd, wet stone.' — 'Medium, saline.' — 'Dungeness crab, roast pork loin, soft cheeses.' — 'Drink now–2028' — none — bottle-white. 5. barrel-select-chardonnay — 2022 — 'Barrel Select Chardonnay' — white — 'Chardonnay, six best barrels' — 13.3% — $52 — 'baked pear · brioche · sea salt' — 'The six best barrels from the Ridge Block, sixteen months on the lees and stirred by hand.' — 'Baked pear, brioche, toasted hazelnut.' — 'Rich but bright, honeyed citrus.' — 'Long, with a touch of sea salt.' — 'Lobster, halibut in brown butter, aged Comté.' — 'Best 2024–2031' — 'Reserve' — bottle-white. 6. pinot-gris — 2024 — 'Pinot Gris' — white — 'Pinot Gris, Creek Block' — 12.5% — $26 — 'white peach · honeysuckle · green almond' — 'Cold-fermented in steel and bottled young. The terrace favorite from May to September.' — 'White peach, honeysuckle, pear skin.' — 'Fresh, juicy, lightly textured.' — 'Short and clean, green almond.' — 'Thai green curry, oysters, summer salads.' — 'Drink now–2027' — none — bottle-white. 7. rose — 2024 — 'Rosé of Pinot Noir' — rose — 'Pinot Noir, pressed at dawn' — 12.2% — $24 — 'wild strawberry · watermelon rind · pink grapefruit' — 'Pressed straight from the vine on the first harvest morning. Pale, bone-dry, usually gone by August.' — 'Wild strawberry, pink grapefruit.' — 'Dry and zesty, watermelon rind.' — 'Short, mouth-watering.' — 'Goat cheese, grilled shrimp, picnic everything.' — 'Drink by 2026' — 'Limited' — bottle-rose. 8. brut — NV — 'Brut Sparkling' — sparkling — 'Chardonnay and Pinot Noir, traditional method' — 12.0% — $46 — 'green apple · lemon curd · toasted almond' — 'Fermented a second time in the bottle and aged 30 months on the yeast before disgorging.' — 'Green apple, lemon curd, warm bread.' — 'Fine bubbles, crisp and creamy.' — 'Long, toasted almond.' — 'Fried chicken, oysters, popcorn.' — 'Drink now–2028' — none — bottle-white. Type swatches: red #6B1F2A, white #D9C27A, rosé #D99A8B, sparkling #E8DDB0.
Layout: Parchment background, padding-top 48px. Grid 4 columns at ≥1280px, 3 at ≥1024px, 2 at ≥640px, 1 below, gap 24px. WineCard: Cream background, 1px Rule border, radius 2px, flex column. Image well: aspect 3/4, Parchment Deep background, overflow hidden, bottle photo object-fit cover object-position 50% 55%; badge (if any) top-left inside the well (Hanken 600 11px uppercase letter-spacing 0.12em, Cream background, Ink text, padding 5px 10px). Body padding 24px: row with swatch dot (10px) + type label (Hanken 600 11px uppercase Muted) left and vintage (Hanken 600 13px tabular) right; name Cormorant 600 26px line-height 1.1, 8px top margin; varietal and ABV Hanken 13px Muted ('Pinot Noir, all four blocks · 13.1%'); descriptors Cormorant 500 italic 19px Ink with ' · ' separators; blurb Hanken 14px line-height 1.6; accordion toggle 'Tasting notes' (Hanken 600 12px uppercase, Plus icon right, 1px Rule top border, 44px high) opening a definition list Nose / Palate / Finish / Pairs with / Cellar (term Hanken 600 12px uppercase Muted, value 14px). Footer row pinned to the card bottom (margin-top auto), 1px Rule top border, padding-top 16px: price Cormorant 500 28px Oxblood tabular left; QtyStepper (two 32px round buttons with Minus/Plus, number 28px wide, aria-labels) and the small primary button 'Add' right. Home Featured wines uses the same card without the accordion.
Motion: Grid layout animation, card hover and add feedback as in Design motion.
4. **Mixed cases** — id 'cases'. Eyebrow 'Mixed cases'. H2 'Let us *pick for you.*' Two cases (id, name, bottles, contents, price, value): 'hillside-six' — 'Hillside Six' — 6 — '2 × Hillside Pinot Noir, 2 × Estate Chardonnay, 1 × Pinot Gris, 1 × Rosé of Pinot Noir' — $168 — 'Worth $194 by the bottle'; 'ridge-dozen' — 'Ridge Dozen' — 12 — '6 × Hillside Pinot Noir, 4 × Founder's Block Pinot Noir, 2 × Library Pinot Noir' — $560 — 'Worth $660 by the bottle'. Each card: name, '6 bottles · ships free' or '12 bottles · ships free', contents as a list with the wine's swatch dot per line, price, the value line in plain Muted text (no strikethrough), primary button 'Add case' that adds the case line (qty 1) and opens the cart. Note under the cards: 'Cases can't be changed online, but the tasting room can swap any bottle if you call (503) 555-0172.'
Layout: Parchment Deep background. Heading row then a 2-column grid gap 24px (1 column under 1024px). Case card: Cream background, 1px Rule border, padding 40px, internal 2-column grid: left (name Cormorant 600 36px, meta Hanken 14px Muted, list Hanken 15px with 10px gaps), right aligned bottom-right (price Cormorant 500 44px Oxblood, value line Hanken 13px Muted, button). Under 640px the card is one column.
Motion: Reveal with stagger.
5. **Shipping strip** — Four items (Lucide icon, title, text): Truck — 'Free on 6 or more' — 'Otherwise $15 flat to any address we ship to.'; CalendarDays — 'Ships Monday to Wednesday' — 'Arrives in 2–5 days, never over a weekend in a warehouse.'; ShieldCheck — 'Adult signature' — 'Someone 21 or older has to sign. FedEx will try three times.'; Snowflake — 'Weather holds' — 'If it's above 85°F or below 25°F on the route, we wait and tell you.'
Layout: Parchment background, padding 80px 0. 4 columns (2 under 1024px, 1 under 640px) separated by 1px Rule vertical lines, each padding 0 32px: icon 24px Oxblood, title Hanken 600 16px, text Hanken 14px Muted.
Motion: Reveal with stagger.
6. **Wine FAQ** — id 'faq'. H2 'Ordering questions.' Five accordion items: 'Which states do you ship to?' — 'Most of them. The checkout checks your ZIP; a few states don't allow direct shipping from wineries, and we'll tell you before you pay.'; 'Can I send wine as a gift?' — 'Yes. Put the recipient's address at checkout and their name in the notes. They'll need to be 21 and home to sign.'; 'How should I store the bottles?' — 'On their side, somewhere dark and steady, ideally 55–60°F. A closet floor beats a kitchen counter.'; 'When will the Library Pinot run out?' — 'There were 140 cases in 2024. When it's gone, the next library release is the 2020, in spring.'; 'Do you use sulfites?' — 'A small amount at bottling, about a third of the legal limit. Nothing else is added except a little yeast for the sparkling.'
Layout: Parchment background. 12-column grid: H2 columns 1–4, accordion columns 6–12. Rows with 1px Rule top borders, question Cormorant 600 24px, 72px high, Plus icon right; answer Hanken 16px max 60ch, padding-bottom 24px. Buttons have aria-expanded and aria-controls.
Motion: Accordion as in Design motion.
7. **Club CTA band** — Cormorant 500 italic 44px Cream: 'Members get the first pour of every library wine.' Text (Cream at 75%): 'Three tiers, from $99 a shipment. Skip or cancel any time.' Primary button 'See the wine club' → ./index.html#club.
Layout: Cellar background, padding 96px 0, container, text left (max 760px), button right, flex space-between align end; stacked under 768px.
Motion: Reveal.
### Visit (`visit.html`)
1. **Visit hero** — Background photo visit-hillside.jpg. Eyebrow (Cream) 'Visit & tastings'. H1 'Come up *the hill.*' Lead (Cream at 88%, max 540px): 'The tasting room is a 1920s hay barn at the top of Larkspur Ridge Road, 50 minutes from downtown Portland. Pour at the bar, walk the rows, stay for the sunset from the terrace.' Row of three chips (on-dark: 1px Cream/35% border, Cream text, 36px high): OpenNowPill, 'Closed Tuesdays', 'Walk-ins welcome up to 4 guests'. Buttons: primary 'Book a visit' → #book, on-photo secondary 'Directions' → #hours.
Layout: Height 82svh, min-height 620px. Image object-fit cover, object-position 50% 70%. Overlay linear-gradient(180deg, rgba(30,23,20,0.5) 0%, rgba(30,23,20,0.12) 40%, rgba(30,23,20,0.72) 100%). Content anchored bottom-left in the container, 80px from the bottom. Under 768px H1 48px, chips wrap, buttons stack.
Motion: Same load scale, parallax and H1 rise as the home hero.
2. **Experiences** — id 'experiences'. Eyebrow 'Three ways to taste'. H2 'Pick your *pace.*' Three experiences (id, name, duration, guests, price, days, slots, description, includes, image): 'hillside' — 'Hillside Tasting' — '45 min' — 'up to 8' — $25 per guest — every open day — 11:00, 11:30, 12:00 … 16:00 (every 30 minutes) — 'Five wines at the bar or on the terrace, poured by whoever made them that week.' — 'Five current-release wines', 'Fee waived with a 2-bottle purchase', 'Walk-ins welcome up to 4' — tasting-flight.webp; 'walk' — 'Vineyard Walk & Taste' — '90 min' — 'up to 8' — $55 per guest — Wed to Sun — 10:00 and 14:00 — 'A slow walk through the south slope and the Founder's Block with someone from the vineyard crew, ending with four wines at the ridge viewpoint.' — 'Four wines at the top of the ridge', 'Gravel paths, about 1.2 miles', 'Boots or sneakers, please' — pruned-vines.jpg; 'library' — 'Cellar Library Seated' — '2 hours' — 'up to 6' — $95 per guest — Fri to Sun — 12:00 and 15:00 — 'A seated tasting in the barrel cellar: six wines including two library vintages, with a board of local cheese and charcuterie.' — 'Six wines incl. two library vintages', 'Cheese and charcuterie board', 'Barrel sample from the current vintage' — tasting-room.webp. Each card button 'Book this' selects the experience in the booking widget and scrolls to #book.
Layout: Parchment background. Heading block, then a 3-column grid gap 24px (1 column under 1024px, cards then horizontal on 768–1023px with image left 40%). Card: Cream background, 1px Rule border. Image aspect 4/3 (object-position 50% 50%; pruned-vines.jpg 50% 60%). Body padding 32px: name Cormorant 600 30px; meta row with Lucide Clock, Users and Tag icons 16px Muted and Hanken 14px ('45 min · up to 8 · $25 per guest'); description Hanken 15px; includes list with Check 16px Olive; footer row with days (Hanken 13px Muted, 'Every day but Tuesday', 'Wednesday to Sunday', 'Friday to Sunday') and the small secondary button 'Book this'.
Motion: Reveal with stagger; image scale 1.04 on card hover.
3. **Booking widget** — id 'book'. Eyebrow 'Book a visit'. H2 'Reserve a *table on the hill.*' Five numbered steps on one page (number Hanken 600 12px Oxblood '01'–'05', step title Cormorant 600 24px): '01 Experience' — three radio tiles (name, duration, price per guest); '02 Date' — MonthCalendar; '03 Time' — slot chips for the chosen experience and date; '04 Guests' — GuestStepper 1–8 (max 6 for library) with the note 'Nine or more? Call us at (503) 555-0172 and we'll set up the barn.'; '05 Your details' — Full name, Email, Phone (optional), Note (optional textarea, 3 rows, placeholder 'Birthdays, allergies, anything we should know'). Availability rules in availability.ts: dates from tomorrow to the end of the month two months ahead; Tuesdays closed for everything; walk only Wed–Sun; library only Fri–Sun; December 24, 25 and 26 closed; a slot is shown as 'Full' (disabled, struck-through time) when (day of month + slot index) % 5 === 0, so availability is deterministic. Summary card: heading 'Your visit', rows Experience / Date (e.g. 'Saturday, November 14') / Time / Guests, line '$25 × 2 guests', Total (Cormorant 500 36px), policy text 'Free to cancel up to 24 hours before. We hold tables for 15 minutes.', primary button 'Request booking' (disabled until experience, date, time, a name and a valid email are set; helper text lists what is missing, e.g. 'Choose a date and time'). Submit calls preventDefault, sends nothing, saves the booking to localStorage brandSlug + ':bookings' and shows the success state: drawn check circle, H3 'You're booked for Saturday, November 14 at 15:00.', text 'Cellar Library Seated for 2 · Reference ' + brandInitials + '-' + 4 random digits + '. Park by the barn and come in through the big doors.', buttons 'Add to calendar' (downloads a .ics file built client-side with lib/ics.ts: summary '[experience] at [BRAND]', the address as location, start and end from the slot and duration, America/Los_Angeles) and text link 'Make another booking' (resets the widget).
Layout: Parchment Deep background. 12-column grid: steps in columns 1–7, summary card in columns 9–12, position sticky top 112px. Steps separated by 1px Rule lines with 32px padding. Experience tiles: 3-column grid gap 12px (stacked under 640px), Cream fill, 1px Rule border, padding 20px; selected tile 2px Oxblood border and a Lucide Check in the corner; role 'radiogroup'. MonthCalendar: header with month name (Cormorant 600 24px) and ChevronLeft/ChevronRight buttons (disabled at the range ends), weekday row Mon–Sun (Hanken 600 11px uppercase Muted), 7-column grid of 44px-high day buttons (Hanken 500 15px tabular); available days Cream fill with 1px Rule border, today outlined in 1px Oak, unavailable days transparent with Muted text at 45% and no border, selected day Oxblood fill with Cream text; role 'grid' with arrow-key navigation and aria-labels like 'Saturday, November 14, available'. Time chips: flex wrap gap 8px, 40px high, padding 0 16px, 1px Rule border; selected Ink fill. GuestStepper: 52px high group with round Minus/Plus buttons and the number in Cormorant 500 32px. Fields in a 2-column grid (1 column under 640px), note full width. Summary card: Cream, 1px Rule border, padding 32px; rows with 1px Rule separators. Under 1024px the summary sits below the steps and is not sticky. Field errors as in the checkout (role alert).
Motion: Selection, price count and success animations as in Design motion.
4. **Hours and getting here** — id 'hours'. Eyebrow 'Hours & directions'. H2 'Plan the drive.' Three columns: 1) 'Tasting room hours' with OpenNowPill and the 7-row hours table (today highlighted as in the Visit teaser), note 'Last pours 30 minutes before closing. Closed December 24–26.'; 2) 'Getting here' — address block with MapPin, then 'From Portland: 50 minutes. Take OR-99W south through Newberg, turn right on Larkspur Ridge Road after the fruit stand, climb 2.1 miles to the gravel drive on your left.' 'From Salem: 35 minutes via OR-22 and OR-99W.' 'Parking: 30 spaces by the barn, two accessible spaces at the door, room for one small bus with notice.' Text link 'Open the estate map' → #map; 3) 'Good to know' — four short items with Lucide icons: Dog 'Leashed dogs welcome on the terrace.', Baby 'Kids welcome; we pour estate grape juice.', Accessibility 'The barn, terrace and restrooms are step-free. The vineyard walk is on gravel slopes.', CarTaxiFront 'No rideshare signal at the top; call (503) 555-0110 for the Amity car service.'
Layout: Parchment background. 3 columns gap 48px (1 column under 1024px), each starting with a Hanken 600 12px uppercase heading and a 1px Rule line. Hours table rows 36px, tabular numbers.
Motion: Reveal with stagger.
5. **Estate map** — id 'map'. Eyebrow 'The estate'. H2 'Find your way *around the ridge.*' An inline SVG map drawn by hand in EstateMap.tsx (no map tiles, no real geography). Features in mapFeatures (id, kind, label, detail): blocks — 'South Block' — 'Pinot Noir · planted 1968 · 11 acres · own-rooted, head-trained on the lower slope'; 'Founder's Block' — 'Pinot Noir · planted 1968 · 4 acres · the oldest vines, source of the Founder's Block wine'; 'Ridge Block' — 'Chardonnay · planted 1991 · 14 acres · the top of the hill at 620 ft'; 'Creek Block' — 'Pinot Gris · planted 2008 · 13 acres · cooler soil along Fern Creek'; buildings — 'Tasting room' — 'The 1920s barn. Bar, terrace and restrooms.'; 'Barrel cellar' — 'Dug into the hill in 1994. Seated library tastings only.'; 'Family home' — 'Private, please.'; 'Parking' — '30 spaces, 2 accessible.'; places — 'Ridge viewpoint' — 'Benches, a view of three valleys and the best sunset on the property.'; 'Oak grove' — 'Picnic tables in the shade. Bring lunch, buy a bottle.'; walking route stops 1 'Barn door', 2 'Founder's Block', 3 'South slope', 4 'Ridge viewpoint'. Legend lists every feature with its symbol; selecting a feature in the map or the legend shows its info card.
Layout: Parchment background. 12-column grid: map columns 1–8, legend columns 10–12 (legend below the map under 1024px). SVG viewBox 0 0 960 600, width 100%, height auto, inside a Parchment Deep frame with 1px Rule border. Drawing: 7 concentric smooth closed contour paths around the ridge top at (600, 170) in 1px Rule; Larkspur Ridge Road as a 14px #CDBFA9 path from (0, 560) curving through (300, 520) to (960, 470), with its name along a textPath in Hanken 600 11px uppercase letter-spacing 0.2em Muted; the gravel drive as a 6px #CDBFA9 path from (320, 522) winding up to parking at (430, 340); Fern Creek as a 3px Sage wavy path down the right edge from (900, 0) to (860, 600) with an italic label; four vine blocks as polygons filled with SVG hatch patterns (1.5px Olive lines every 7px, a different rotation per block: 20°, -30°, 0°, 60°) at 55% opacity with a 1px Olive outline and a label in Cormorant 600 italic 18px Ink; the tasting room as a 72×44 Oxblood rect with a small gable roof triangle at (470, 290); the barrel cellar as an Ink semicircle door at (560, 250); the family home as a 40×30 Muted rect at (680, 360); parking as a 56×36 rounded rect with 'P' in Hanken 600; the oak grove as nine circles r 10–16 in Oak at 30% opacity near (250, 330); the ridge viewpoint as a 6-point star at (600, 160) with '620 ft'; the walking route as a 2.5px Oxblood dashed path (dasharray 6 6) from the barn through stops 2–4 and back, with stop markers as 22px Oxblood circles holding Cream numbers 1–4; a compass rose with 'N' top-right and a scale bar '0 — 100 m' bottom-left. Every block, building and place is a focusable <g> (tabIndex 0, role button, aria-label = label) and responds to hover, focus, click and Enter. Info card: a 280px Cream panel with 1px Rule border fixed in the top-left corner of the map frame (not a floating tooltip), showing kind (eyebrow), label (Cormorant 600 24px) and detail; default shows 'Tasting room'. Legend: grouped lists 'Vine blocks', 'Buildings', 'Places', 'Walking route' with small inline SVG symbols, each item a button that selects the feature (aria-pressed).
Motion: Map entrance stagger and hover outline as in Design motion.
6. **Visit FAQ** — id 'faq'. H2 'Before you come.' Six accordion items: 'Do I need a booking?' — 'Not for the Hillside Tasting with up to 4 guests; we keep half the bar for walk-ins. The walk and the library tasting are booking only.'; 'Can we bring food?' — 'Picnics are welcome in the oak grove. Please don't bring outside wine.'; 'Is there food for sale?' — 'Cheese and charcuterie boards ($22) and a few snacks from neighbors in Amity.'; 'What if it rains?' — 'Then it's Oregon. The barn has room for everyone and the vineyard walk goes ahead with umbrellas unless there's lightning.'; 'Can we host a private event?' — 'Up to 40 guests in the barn on Tuesdays, when we're closed to the public. Call or email us.'; 'Do club members need to book?' — 'Members can walk in for the Hillside Tasting any time; for the library tasting, book like everyone else and the fee is taken off at the bar.'
Layout: Same layout as the Wine FAQ on wines.html.
Motion: Accordion as in Design motion.
7. **CTA band** — Cormorant 500 italic 44px Cream: 'Can't make it up the hill? The wines ship.' Text (Cream at 75%): 'Free shipping on 6 bottles or more, Monday to Wednesday.' Primary button 'Shop the wines' → ./wines.html.
Layout: Same as the Club CTA band on wines.html.
Motion: Reveal.
## Assets
- image: CC0 photos from Wikimedia Commons, downloaded with curl -L -o into public/images/ (exact URL → path · where · alt · source page · author · license): https://thumb.wikimedia.org/wikipedia/commons/thumb/c/c4/Soleil_%C3%A9crasant_sur_Rosenwiller_et_sa_grande_colline_%2850020702136%29.jpg/1920px-Soleil_%C3%A9crasant_sur_Rosenwiller_et_sa_grande_colline_%2850020702136%29.jpg → public/images/hero-vineyard.jpg · Home hero · alt 'Golden autumn vineyard rows on a hillside above a small village at sunset' · https://commons.wikimedia.org/wiki/File:Soleil_%C3%A9crasant_sur_Rosenwiller_et_sa_grande_colline_(50020702136).jpg · Valentin F.R. · CC0 1.0. https://thumb.wikimedia.org/wikipedia/commons/thumb/f/ff/Vinyard_P%C3%ABrmet.jpg/1920px-Vinyard_P%C3%ABrmet.jpg → public/images/vines-spring.jpg · Home Estate intro · alt 'Young green grapevines on wooden posts in a spring vineyard' · https://commons.wikimedia.org/wiki/File:Vinyard_P%C3%ABrmet.jpg · Albinfo · CC0 1.0. https://thumb.wikimedia.org/wikipedia/commons/thumb/a/a7/Pinot_Noir_%C3%A0_Verzenay.jpg/1920px-Pinot_Noir_%C3%A0_Verzenay.jpg → public/images/grapes-pinot.jpg · Home Harvest calendar · alt 'Dark Pinot Noir grape clusters hanging under green vine leaves' · https://commons.wikimedia.org/wiki/File:Pinot_Noir_%C3%A0_Verzenay.jpg · Renhour48 · CC0 1.0. https://thumb.wikimedia.org/wikipedia/commons/thumb/0/05/Mecsekn%C3%A1dasd%2C_Wine_cellar_01.jpg/1920px-Mecsekn%C3%A1dasd%2C_Wine_cellar_01.jpg → public/images/cellar-tunnel.jpg · Home Wine club · alt 'Thousands of dark wine bottles stacked in a vaulted stone cellar' · https://commons.wikimedia.org/wiki/File:Mecsekn%C3%A1dasd,_Wine_cellar_01.jpg · PAvdK · CC0 1.0. https://thumb.wikimedia.org/wikipedia/commons/thumb/b/b5/Vineyard_of_Camulos_Ranch_MET_DP152259.jpg/1920px-Vineyard_of_Camulos_Ranch_MET_DP152259.jpg → public/images/archive-vineyard.jpg · Home Story timeline (cropped with scale 1.3 so the mount and handwritten title never show) · alt 'Archival photograph of head-trained vines in a dry valley vineyard, 1880s' · https://commons.wikimedia.org/wiki/File:Vineyard_of_Camulos_Ranch_MET_DP152259.jpg · Carleton Watkins (The Metropolitan Museum of Art) · CC0 1.0. https://thumb.wikimedia.org/wikipedia/commons/thumb/d/d3/Vineyard_in_Slovenia_2008.jpg/1920px-Vineyard_in_Slovenia_2008.jpg → public/images/visit-hillside.jpg · Visit hero · alt 'Hillside vineyard with a small white farm house in warm evening light' · https://commons.wikimedia.org/wiki/File:Vineyard_in_Slovenia_2008.jpg · IgorMar · CC0 1.0. https://thumb.wikimedia.org/wikipedia/commons/thumb/9/95/Cape_Winelands_-_Stellenbosch3785.jpg/1920px-Cape_Winelands_-_Stellenbosch3785.jpg → public/images/pruned-vines.jpg · Visit Experiences, Vineyard Walk card · alt 'Rows of pruned old vines with fresh green grass in spring' · https://commons.wikimedia.org/wiki/File:Cape_Winelands_-_Stellenbosch3785.jpg · lumoplank · CC0 1.0.
- image: Template photos made for this design (free to redistribute with the template). Download each with curl -L -o into public/images/: https://media.vibefather.ai/assets/4f95b0e1-e92a-4d0d-ae6a-114c9c4faa84/bottle-red.webp → public/images/bottle-red.webp (WineCards for Hillside Pinot Noir, Founder's Block, Library Pinot Noir; cart thumbnails; alt 'Bottle of [wine name] on an oak plank'); https://media.vibefather.ai/assets/4f95b0e1-e92a-4d0d-ae6a-114c9c4faa84/bottle-white.webp → public/images/bottle-white.webp (WineCards for Estate Chardonnay, Barrel Select Chardonnay, Pinot Gris, Brut Sparkling; cart thumbnails; alt 'Bottle of [wine name] on an oak plank'); https://media.vibefather.ai/assets/4f95b0e1-e92a-4d0d-ae6a-114c9c4faa84/bottle-rose.webp → public/images/bottle-rose.webp (WineCard for Rosé of Pinot Noir; cart thumbnail; alt 'Bottle of Rosé of Pinot Noir on an oak plank'); https://media.vibefather.ai/assets/4f95b0e1-e92a-4d0d-ae6a-114c9c4faa84/barrel-room.webp → public/images/barrel-room.webp (Home Cellar band and Wines masthead band; alt 'Rows of oak barrels in a vaulted stone cellar lit by warm lamps'); https://media.vibefather.ai/assets/4f95b0e1-e92a-4d0d-ae6a-114c9c4faa84/tasting-room.webp → public/images/tasting-room.webp (Home Visit teaser and the Cellar Library Seated card; alt 'Oak bar with wine glasses inside a restored timber barn'); https://media.vibefather.ai/assets/4f95b0e1-e92a-4d0d-ae6a-114c9c4faa84/tasting-flight.webp → public/images/tasting-flight.webp (Hillside Tasting card; alt 'Five glasses of wine from sparkling to red on a terrace table at sunset'). Mixed case lines and membership lines in the cart use code-drawn thumbnails (swatch stripes for cases, a Cellar square with a Lucide Wine icon for memberships).
- image: Write ASSETS.md at the project root with a table: path, source URL, author, license — one row for each of the thirteen images (the seven CC0 photos with the source pages, authors and licenses listed above; the six template photos list source 'media.vibefather.ai, made for this template', author 'VibeFather', license 'Distributed with the template'), plus rows for @fontsource/cormorant-garamond and @fontsource-variable/hanken-grotesk (OFL-1.1) and lucide-react (ISC). If you change [REGION] or [VARIETIES], keep these photos or replace them only with other CC0 / public-domain files (Wikimedia Commons files marked CC0 or Public Domain, Openverse with the CC0 filter, museum open-access collections), never Unsplash, Pexels or Pixabay, and replace the bottle photos only with your own photos of your own unlabeled or own-labeled bottles shot the same way.
- icon: lucide-react only: ShoppingBag, Menu, X, Plus, Minus, Check, ArrowRight, ArrowUpRight, ChevronLeft, ChevronRight, MapPin, Phone, Mail, Clock, Users, Tag, CalendarDays, Truck, ShieldCheck, Snowflake, Leaf, Wine, Dog, Baby, Accessibility, CarTaxiFront. Stroke width 1.5, 16–24px, color inherits. public/favicon.svg hand-written: viewBox 0 0 32 32, a 32×32 rect rx 4 filled #6B1F2A, and a cluster of six Cream (#FBF7F0) circles r 3.2 arranged as a grape bunch (rows of 3, 2, 1 centered at x 16, y from 11 to 22) with a 1.5px Cream stem line above. No other logo: the estate name is always set as type.
- font: Install @fontsource/cormorant-garamond and @fontsource-variable/hanken-grotesk and import them in src/fonts.ts as listed in Setup. Vite bundles the woff2 files into dist/.
- image: Drawn in code: the estate map (inline SVG with hatch patterns), the calendar phase bars, type swatch dots, the free-shipping meter, the drawn success check circles, dividers and the favicon. No other bitmaps, no illustrations, no map tiles.
## Don'ts
- No backend of any kind: no server code, API routes, databases, auth, payment providers, email services, analytics or third-party APIs. Checkout and booking forms call preventDefault and only change local state and localStorage; nothing is submitted, charged or sent.
- Do not load fonts from fonts.googleapis.com, fonts.gstatic.com, Adobe Fonts or any CDN. Self-host through the two Fontsource packages only.
- No CDN <script>, <link> or import maps. Every script, style, font, icon and image is in the project and bundled into dist/.
- No hotlinked images: every photo is downloaded into public/images/ once and served from there, and every third-party file is listed in ASSETS.md.
- No source maps in the production build (build.sourcemap false), and src/ is not copied into dist/.
- Relative asset paths (Vite base './'). Internal links are hash anchors or file names such as ./index.html, ./index.html#club, ./wines.html#cases and ./visit.html#book, never a bare directory or a leading slash.
- Do not change the stack (Vite 5 + React 18 + TypeScript + Tailwind CSS 3.4 + Motion + lucide-react + Fontsource, three HTML entries) unless the user asks. No router library, no UI kit, no date-picker or map library, no 3D.
- No real winery, estate, vineyard or wine brand names, no appellation-protected label names, no real people. Every person, wine, block, road, creek and figure is invented; only the region and state may be real.
- No real bottle labels, logos, crests, cooperage stamps or signs in any image, and no AI-made label art. Bottles are shown only in the listed unlabeled photos. The estate has no logo beyond its typeset name and the favicon.
- No copy, tasting notes or slogans from any real winery's site; use only the copy given here for the default values.
- No people's faces in photos and no recognizable landmarks used as branding. Use only the listed images; no Unsplash, Pexels, Pixabay or other stock sites with their own licenses.
- No real maps or map tiles (Google Maps, Mapbox, OpenStreetMap embeds or iframes): the estate map is drawn in SVG by hand.
- No commercial or custom fonts: only Cormorant Garamond and Hanken Grotesk (OFL).
- Only dependencies under MIT, ISC, BSD, Apache-2.0, 0BSD, CC0 or Unlicense (OFL for fonts). No Aceternity UI, Tailwind Plus / Tailwind UI or purchased template code; write every effect from scratch.
- One accent only: Oxblood (with Oxblood Light on dark backgrounds). Olive, Oak and Sage are for small marks, never for buttons. No gradients except the photo overlays given, no glows, no glassy cards, no drop shadows, no rounded pill cards.
- The age gate must appear on all three pages until confirmed and must not be skippable by scrolling; keep the 'enjoy responsibly' and 21+ notices in the footer and the 21+ checkbox in checkout.
- Respect prefers-reduced-motion exactly as described under Design motion. Every interactive element is keyboard reachable with a visible 2px Oxblood focus ring; dialogs trap focus; accordions use aria-expanded; the calendar and month strip support arrow keys; form errors use role alert.
- Must render at 1440×900 and 390×844 with zero console errors and no horizontal page scroll (only the mobile filter chips scroll inside themselves). localStorage access is wrapped in try/catch so private mode never throws.
- Keep dist/ under 20 MB (target under 12 MB).
- No lorem ipsum, filler or hype words. No meta descriptions, Open Graph tags, JSON-LD or sitemap: only the <title> and favicon.
---
— Prompt by VibeFather · https://vibefather.ai/t/family-winery-and-vineyard-website · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown
Free for personal projects under CC BY-NC 4.0. Commercial use comes with Pro.
DESIGN.md
The design system on its own — colors, type, spacing and motion. Apply this look to a project you already have.
---
name: "Family Winery and Vineyard Website"
colors:
parchment: "#F4EEE3"
parchment_deep: "#EAE1D2"
cream: "#FBF7F0"
ink: "#2A211C"
cellar: "#1E1714"
cellar_soft: "#2E2420"
muted: "#6E6258"
rule: "#D8CCBA"
oxblood: "#6B1F2A"
oxblood_deep: "#521722"
oxblood_light: "#C98B8F"
olive: "#5E6340"
oak: "#8C5E34"
sage: "#9FAE9A"
typography:
display_h1_h2_h3_wine_names_timeline_years_prices_in_large_sizes_tasting_note_descriptors_italic_the_wordmark: { family: "Cormorant Garamond", weights: [500, 600] }
text_and_ui_body_eyebrows_buttons_nav_form_fields_tables_captions_numbers_font_variant_numeric_tabular_nums_for_prices_and_hours: { family: "Hanken Grotesk", weights: [400, 500, 600] }
spacing: "8px base unit. Container max-width 1320px, centered, side padding 48px desktop, 32px tablet, 20px under 640px. 12-column grid, column gap 24px. Section vertical padding 136px desktop, 96px under 1024px, 80px under 640px. Type scale: H1 clamp(48px, 7vw, 112px) Cormorant Garamond 500, line-height 0.98, letter-spacing -0.01em; H2 clamp(38px, 4.6vw, 72px) Cormorant 500, line-height 1.02; H3 28px Cormorant 600, line-height 1.15; italic phrases in headings use Cormorant 500 italic (marked with *asterisks* in content.ts and rendered as <em>); lead paragraph Hanken 19px / 1.6 Ink at 85% opacity; body Hanken 400 16px / 1.7 (max-width 62ch); eyebrow Hanken 600 12px uppercase letter-spacing 0.18em Muted, preceded by a 24px × 1px Oak line with 12px gap; caption Hanken 13px Muted. Buttons: height 52px, padding 0 28px, Hanken 600 14px uppercase letter-spacing 0.12em. Primary: Oxblood fill, Cream text. Secondary: 1px Ink border, Ink text, transparent (on photos: 1px Cream border, Cream text). Small buttons 40px high, padding 0 18px, 12px text. Inputs: height 52px, 1px Rule border, Cream fill, 16px Hanken, focus border Oxblood. Focus ring everywhere: 2px Oxblood outline with 3px offset (Oxblood Light on dark)."
radius: "2px on cards, buttons, inputs, chips, photos and the cart drawer edge — nearly square. 999px only for the cart count badge, the open-now dot, the type swatch dots, qty stepper buttons and map stop markers."
---
# Family Winery and Vineyard Website — Design System
Apply this design system to an existing project. It describes the look and feel only; for the full site, use prompt.md.
## Colors
- **Parchment** `#F4EEE3` — Page background on all three pages, header background after scroll, cart drawer background.
- **Parchment Deep** `#EAE1D2` — Alternate section background (Timeline, Booking, Mixed cases), wine card image wells, input fill, hover fill for rows and month cells.
- **Cream** `#FBF7F0` — Card surfaces (wine cards, experience cards, booking summary), text on photographs and on Cellar backgrounds.
- **Ink** `#2A211C` — Headlines and body text on light backgrounds, primary outline buttons, icon color.
- **Cellar** `#1E1714` — Wine Club section, footer, age gate, mobile menu, photo overlays (as rgba(30,23,20,x)).
- **Cellar Soft** `#2E2420` — Tier cards and hairlines on Cellar backgrounds.
- **Muted** `#6E6258` — Secondary text, captions, eyebrows, disabled calendar days (at 45% opacity).
- **Rule** `#D8CCBA` — 1px hairlines, card borders, input borders, map contour lines, timeline base line.
- **Oxblood** `#6B1F2A` — The one accent: primary buttons, prices, cart badge, selected states, timeline progress line, focus ring, map tasting room and walking route, red wine swatch.
- **Oxblood Deep** `#521722` — Primary button hover and pressed state.
- **Oxblood Light** `#C98B8F` — Oxblood replacement for text and lines on Cellar backgrounds (prices, active tier border).
- **Olive** `#5E6340` — Quiet second color: growth phase in the harvest calendar, vine block hatching on the map, 'Organic' and 'In stock' tags, open-now dot.
- **Oak** `#8C5E34` — Timeline years, ripening phase in the calendar, oak grove on the map, small numerals. Never for body text.
- **Sage** `#9FAE9A` — Creek line on the map and the rest-phase bar in the calendar.
## Typography
- **Display: H1, H2, H3, wine names, timeline years, prices in large sizes, tasting-note descriptors (italic), the wordmark** — Cormorant Garamond (OFL), weights 500/600. Self-host the font files.
- **Text and UI: body, eyebrows, buttons, nav, form fields, tables, captions, numbers (font-variant-numeric tabular-nums for prices and hours)** — Hanken Grotesk (OFL), weights 400/500/600. Self-host the font files.
## Spacing & shape
- Spacing: 8px base unit. Container max-width 1320px, centered, side padding 48px desktop, 32px tablet, 20px under 640px. 12-column grid, column gap 24px. Section vertical padding 136px desktop, 96px under 1024px, 80px under 640px. Type scale: H1 clamp(48px, 7vw, 112px) Cormorant Garamond 500, line-height 0.98, letter-spacing -0.01em; H2 clamp(38px, 4.6vw, 72px) Cormorant 500, line-height 1.02; H3 28px Cormorant 600, line-height 1.15; italic phrases in headings use Cormorant 500 italic (marked with *asterisks* in content.ts and rendered as <em>); lead paragraph Hanken 19px / 1.6 Ink at 85% opacity; body Hanken 400 16px / 1.7 (max-width 62ch); eyebrow Hanken 600 12px uppercase letter-spacing 0.18em Muted, preceded by a 24px × 1px Oak line with 12px gap; caption Hanken 13px Muted. Buttons: height 52px, padding 0 28px, Hanken 600 14px uppercase letter-spacing 0.12em. Primary: Oxblood fill, Cream text. Secondary: 1px Ink border, Ink text, transparent (on photos: 1px Cream border, Cream text). Small buttons 40px high, padding 0 18px, 12px text. Inputs: height 52px, 1px Rule border, Cream fill, 16px Hanken, focus border Oxblood. Focus ring everywhere: 2px Oxblood outline with 3px offset (Oxblood Light on dark).
- Radius: 2px on cards, buttons, inputs, chips, photos and the cart drawer edge — nearly square. 999px only for the cart count badge, the open-now dot, the type swatch dots, qty stepper buttons and map stop markers.
## Motion
- Easing: --ease-out cubic-bezier(0.22, 0.61, 0.36, 1) for reveals and drawers; --ease-io cubic-bezier(0.65, 0, 0.35, 1) for accordions, month switches and booking steps. Nothing bounces.
- Reveal: blocks wrapped in <Reveal> start at opacity 0, translateY(20px) and animate to rest over 800ms --ease-out when 15% visible (Motion whileInView, viewport once). Siblings in a list stagger by 80ms (index prop).
- Hero photos (home and visit): on load the image scales from 1.08 to 1.0 over 2400ms --ease-out; while scrolling, the image translates from 0 to 12% of its height as the hero scrolls out (Motion useScroll target hero, offset ['start start', 'end start'], useTransform), and the headline block fades to opacity 0.2 and moves -40px over the same range. H1 lines rise from translateY(30px) and opacity 0 with 120ms stagger, starting 200ms after load (or after the age gate closes).
- Image bands (home CellarBand, wines masthead band): parallax, the image inside its overflow-hidden frame moves from -8% to 8% of its height across the frame's scroll progress.
- Timeline: a 2px Oxblood line over the 1px Rule base line grows with scroll (scaleY 0 → 1, transform-origin top, useScroll on the list with offset ['start 70%', 'end 60%']). Each entry's year dot fills Oxblood when the line reaches it (entry in view at 60%).
- Wine cards: on hover the bottle photo scales to 1.04 over 700ms --ease-out and the card border turns Ink. 'Add to cart' click: button content crossfades to a Check icon and 'Added' for 1400ms; the header cart badge scales 1 → 1.35 → 1 over 400ms and its number updates.
- Cart drawer: Cellar overlay fades to 55% opacity over 300ms; the drawer slides in from the right (x 100% → 0) over 420ms --ease-out; closing reverses in 320ms. Checkout steps crossfade with a 16px horizontal slide, 260ms --ease-io (AnimatePresence mode 'wait'). Line removal collapses height over 240ms.
- Wine grid filtering: cards use Motion layout with AnimatePresence mode 'popLayout'; leaving cards fade and scale to 0.96 over 200ms, remaining cards glide to their new positions over 400ms --ease-io.
- Accordions (tasting notes, FAQ): height 0 → auto and opacity 0 → 1 over 320ms --ease-io; the Plus icon rotates 45° into an X.
- Harvest calendar: changing the month crossfades the detail panel (opacity and 12px y) over 300ms --ease-io; the selected month's 2px Oxblood top bar slides between cells with Motion layoutId.
- Booking: selecting an experience, date or slot animates the selected tile's border and fill over 150ms; the summary price counts to the new total over 400ms; the success state replaces the widget with a fade and a check circle whose stroke draws over 600ms (pathLength 0 → 1).
- Header: transparent over the photo heroes with Cream text; after 40px of scroll it gets Parchment at 94% opacity, backdrop-filter blur(10px), Ink text and a 1px Rule bottom border, 250ms transition. On wines.html it is solid from the start.
- Age gate: overlay fades in 400ms on first load; on confirm the card fades and moves up 16px, the overlay fades out over 500ms, then the hero animation starts.
- Map: when the map enters view, vine blocks fade in with 100ms stagger, then the walking route fades in and its four stop markers pop from scale 0.6 to 1 with 120ms stagger. Hovered or focused blocks rise to full opacity and get a 2px Ink outline over 150ms.
- Links: .link-draw grows a 1px currentColor underline from 0% to 100% width over 300ms --ease-out on hover and focus-visible.
- prefers-reduced-motion: reduce — disable the hero scale and parallax, image band parallax, H1 rise, reveals (render at rest), timeline growth (show the full line), grid layout animation, map stagger, count-ups and drawer slide (drawer and overlay appear with a 0ms fade). Color and border hover changes stay. Use CSS @media in index.css plus Motion's useReducedMotion in components.
## Imagery
Real photography only, warm and natural: seven CC0 photos from Wikimedia Commons (golden autumn vineyard above a village, young vines in spring, Pinot Noir clusters on the vine, a vaulted bottle cellar, a hillside vineyard with a small white farm house at golden hour, pruned vines in spring, an 1880s archival vineyard photograph) and six photos made for this template (three unlabeled estate bottles — red, white, rosé — shot identically on an oak plank against limestone, the barrel cellar, the barn tasting room, and a tasting flight on the terrace). No people's faces anywhere, no readable labels, logos or signs. Every photo uses object-fit cover with the object-position given under Assets, square-ish 2px corners, no shadow; photos on Parchment get a 1px Rule outline. Captions sit below in Hanken 13px Muted. Photos under text get a Cellar gradient overlay as specified per section. Drawn in code: the favicon, the wordmark (type only), the estate map, calendar phase bars, type swatch dots, the check circle, dividers. Icons: lucide-react only, stroke width 1.5.
## Tone
Warm, grounded and precise, like a winemaker talking at the barn door. Concrete numbers (acres, cases, months in barrel, prices, hours), plain words for tasting notes, a little dry humor. No wine-snob jargon without explanation, no hype words, no exclamation marks.
---
— Prompt by VibeFather · https://vibefather.ai/t/family-winery-and-vineyard-website · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown