Skip to content
VibeFather
Join

2 cases built from this template

Same prompt, different [VARIABLES]. Click one to preview it above.

About this template

Brightwell is a two-page website for a local health practice that wants to look like a place people already trust. The default build is Wrenfield Dental, an invented family and cosmetic dental clinic in the invented town of Calder Springs. The home page carries the full story: a dismissible emergency banner, a hero with a live open-now card and the next free slot, a reassurance strip, an $89 new-patient offer, six treatment cards with price ranges, a photo gallery of the clinic interior, the team, reviews, insurance and payment plans, a booking section with opening hours and a drawn map, and an FAQ about pain and cost. The second page lists sixteen treatments by category, each with a price range, duration, insurance note and a short what-to-expect list, followed by a clear aligner feature and a payment plan calculator.

It suits dentists, physiotherapists, vets, dermatology and optometry practices, and the freelancers and small studios who build sites for them. The look is calm and clinical but warm: a linen background, soft sage surfaces, deep teal text and one clay accent kept for booking buttons and the emergency banner. Headlines are set in Fraunces, body text in Figtree. The team appears as monogram avatars with credentials instead of portraits, and every photograph shows rooms and equipment, never patients.

The appointment request form works entirely in the browser. Visitors pick a reason, choose one of the next fourteen days and a time slot from chips grouped by morning, afternoon and evening, fill in their details and see a confirmation with a reference number. Nothing is sent anywhere. Links from the treatments page preselect the reason.

To adapt it, change the brand, town, practice type, new-patient offer and phone number, then edit the treatments, prices, hours and team in the single content file. Swap the interior photos for your own rooms.

The template prompt

The live demo was built from exactly this text — nothing added. The other cases only change the values of the [VARIABLES].

# Dental Clinic Website

Build this website exactly as described below. Replace the [VARIABLES] with your own values; keep everything else.

## Brief
A two-page website for [BRAND], an independent practice offering [SPECIALTY] in [CITY], a mid-size town. The look is calm, clean and trustworthy, clinical but warm: linen and soft sage surfaces, deep teal ink, one clay accent, generous whitespace, rounded cards and real photographs of the clinic's rooms and equipment (never patients). index.html carries the whole visit decision: emergency banner, hero with a live open-now card, reassurance strip, new-patient offer ([NEW_PATIENT_OFFER]), six treatment cards with price ranges, a clinic gallery, the team as monogram cards with credentials, patient reviews, insurance and payment plans, a client-side appointment request form with a day strip, time-slot chips and a success state, opening hours with an open-now indicator, a drawn map, an FAQ about pain and cost and a footer. treatments.html lists every treatment by category with a price range, duration, insurance note and what to expect, a clear aligner feature, a payment plan calculator and a closing call-to-action. It must read like a real practice that has been open for years: concrete prices, hours, an invented street address, named (invented) clinicians and patients, and plain-spoken answers.

- Audience: Local adults booking for themselves or their family: parents with young children, people who have avoided the dentist for years and are nervous, and people comparing costs because they have no insurance or a basic plan. Most visit on a phone, often from a search, and want to know three things fast: is it near me, what will it cost, and can I get in soon.
- Goal: Get the visitor to send an appointment request. Primary CTA everywhere: 'Book a visit' (to ./index.html#book). Secondary: call [PHONE] (tel: link) and 'See treatments & prices' (./treatments.html). For emergencies the banner and booking side panel push the phone call instead of the form.
- Tone: Warm, plain and reassuring, like a good receptionist on the phone. Short sentences, real numbers, no jargon without a plain explanation, no fear tactics, no hype words (no world-class, state-of-the-art, cutting-edge, best-in-class, revolutionary). Address the reader as 'you'; the practice speaks as 'we'.

## Stack
- Framework: Vite 5 + React 18 + TypeScript
- Styling: Tailwind CSS 3.4
- Libraries: react (MIT), react-dom (MIT), lucide-react (ISC), tailwindcss (MIT), postcss (MIT), autoprefixer (MIT), vite (MIT), @vitejs/plugin-react (MIT), typescript (Apache-2.0), @fontsource-variable/fraunces (OFL-1.1), @fontsource-variable/figtree (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. Two real HTML entry files at the project root: index.html (mounts src/home.tsx) and treatments.html (mounts src/treatments.tsx). Both share the same components, styles and content file.
  - vite.config.ts: base './', plugins [react()], build { outDir 'dist', sourcemap false, assetsInlineLimit 0, rollupOptions { input { index: resolve(__dirname, 'index.html'), treatments: resolve(__dirname, 'treatments.html') } } }. Do not copy src/ into dist/.
  - Tailwind 3.4 through PostCSS (tailwindcss + postcss + autoprefixer), content ['./index.html', './treatments.html', './src/**/*.{ts,tsx}']. In tailwind.config.ts add every color under Design to theme.extend.colors with the lowercase keys linen, paper, sage-50, sage-100, sage-300, teal, teal-700, ink, slate, line, clay, clay-700, clay-50, open; fontFamily display ['Fraunces Variable', 'Georgia', 'serif'] and sans ['Figtree Variable', 'system-ui', 'sans-serif']; boxShadow card '0 1px 2px rgba(28,38,36,0.06), 0 8px 24px -12px rgba(28,38,36,0.18)' and lift '0 2px 4px rgba(28,38,36,0.06), 0 18px 40px -16px rgba(28,38,36,0.28)'.
  - In both entry files import '@fontsource-variable/fraunces', '@fontsource-variable/figtree' and './index.css'.
  - File layout: src/content.ts (every string, price, treatment, team member, review, FAQ, opening hours, image path and alt text, typed), src/index.css (Tailwind layers, .reveal styles, keyframes pulse-dot and banner-collapse, reduced-motion overrides), src/lib/hours.ts (open-now status, today's row, next opening), src/lib/slots.ts (day strip and time-slot generation), src/lib/reveal.ts (one shared IntersectionObserver), src/lib/params.ts (reads ?treatment= from the URL).
  - Components in src/components/: EmergencyBanner, Nav, MobileMenu, Footer, Hero, OpenNowCard, Reassurance, NewPatientOffer, TreatmentPreview, Gallery, Team, MonogramAvatar, Reviews, Stars, InsurancePlans, BookingForm, DayStrip, SlotPicker, BookingSuccess, VisitPanel, HoursTable, MapDrawing, Faq, Accordion, TreatmentsHeader, PricePromise, CategoryNav, TreatmentCategory, TreatmentRow, AlignerFeature, PaymentCalculator, ClosingCta. Pages in src/pages/Home.tsx and src/pages/Treatments.tsx.
  - 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 never fetches anything.
  - public/favicon.svg as described in the Head section. index.html <title>[BRAND] · [SPECIALTY] in [CITY]</title> (capitalize the first letter of the specialty); treatments.html <title>Treatments & prices · [BRAND]</title>. lang en, theme-color #F7F4EE. No other head tags beyond charset, viewport, title, theme-color and the favicon link.
  - dist/ holds index.html, treatments.html, hashed JS/CSS, the woff2 fonts, favicon.svg and the nine images. Keep it under 8 MB.

## Variables
- [BRAND] — Practice name (default: "Wrenfield Dental"). Shown in the nav wordmark, titles, footer, booking success text and FAQ answers. The care plan is called '[BRAND] Care Plan' with the trailing word Dental dropped ('Wrenfield Care Plan').
- [CITY] — Town or city (default: "Calder Springs"). An invented or real town name. Used in the hero eyebrow, titles, the address block and the footer.
- [SPECIALTY] — Practice type (default: "family & cosmetic dentistry"). Lowercase phrase. Drives the hero eyebrow, the titles and all treatments, prices, team credentials, FAQ answers and photos. Rewrite those for another kind of practice.
- [NEW_PATIENT_OFFER] — New-patient offer (default: "$89 first visit: exam, cleaning & X-rays"). Price first, then what it includes. Feeds the offer section, the hero trust row, the booking reason list and the FAQ.
- [PHONE] — Phone number (default: "(320) 555-0142"). Use a 555-01xx number for demos. Shown in the emergency banner, nav, booking panel, footer and as tel: links (digits only in the href, e.g. tel:+13205550142).
- [CREDIT] — keep a small "Template by VibeFather" link to https://vibefather.ai/t/dental-clinic-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
- Linen `#F7F4EE` — Page background, text on Teal and Clay surfaces
- Paper `#FFFFFF` — Cards, form surface, floating hero cards, inputs
- Sage 50 `#EEF3EF` — Alternating section background (Reassurance, Team, Book & visit), chip backgrounds
- Sage 100 `#DFE8E1` — Icon circles, monogram avatar tint A, selected day chip border, hover fill of ghost buttons
- Sage 300 `#B7CBBE` — Monogram avatar tint B, rating bar track, map park areas, decorative arches
- Teal `#1F4A47` — Headings, wordmark, secondary buttons, selected chips, footer and closing CTA background
- Teal 700 `#163634` — Teal button hover, footer bottom row
- Ink `#1C2624` — Body text on light surfaces
- Slate `#5B6966` — Secondary text, captions, field help, durations, unavailable slots
- Line `#DCE3DD` — 1px borders of cards, inputs, dividers, table rows
- Clay `#BF4F35` — The only accent: primary 'Book a visit' buttons, emergency banner background, star icons, focus ring, the map pin. Never used for large surfaces other than the banner.
- Clay 700 `#A3412A` — Clay button hover and active
- Clay 50 `#FBEAE4` — Emergency notice box in the booking form and side panel, error field background
- Open `#2F7D5B` — Open-now dot and text, success check, 'often covered' insurance chip text

### Typography
- Display (H1, H2, prices, big rating number, monograms, wordmark): Fraunces Variable (OFL), weights 400/500/600
- Text (body, nav, buttons, labels, chips, form fields, H3): Figtree Variable (OFL), weights 400/500/600/700

### Layout & motion
- Spacing: 8px base unit. Container max-width 1200px, side gutter clamp(20px, 4vw, 40px). Section vertical padding 112px on desktop, 72px under 768px. H1 Fraunces 500 clamp(42px, 5.4vw, 72px), line-height 1.04, letter-spacing -0.02em, color Teal. H2 Fraunces 500 clamp(32px, 3.6vw, 48px), line-height 1.1, letter-spacing -0.015em, Teal; one word or short phrase per H2 is set in Fraunces 400 italic (marked with <em> in the copy below). H3 Figtree 600 20px/1.3 Ink. Body Figtree 400 17px/1.65 Ink (16px under 768px); lead paragraphs 19px Slate. Eyebrows Figtree 600 13px uppercase, letter-spacing 0.12em, Teal at 80%, with a 6px Clay dot 10px before the text. Prices Fraunces 500 with font-variant-numeric tabular-nums. Section headers: eyebrow, H2 and a max-width 56ch lead, 48px below the header before content.
- Radius: Cards and photo tiles 24px, the new-patient offer card and the booking form card 28px, inputs and select 14px, buttons, chips, the day strip chips and time-slot chips fully rounded (999px), icon circles and monogram avatars are circles. Primary buttons are 52px tall pills (44px in the nav), padding 0 26px, Figtree 600 16px, Clay background, Linen text, with a lucide ArrowRight 18px that moves 3px right on hover. Secondary buttons are the same size with a 1.5px Teal border, Teal text, transparent background, Sage 100 fill on hover.
- Motion: Easing everywhere: cubic-bezier(0.22, 1, 0.36, 1). Durations: 200ms for hovers and chip selection, 300ms for accordions and menus, 600ms for reveals.
- Motion: Reveal: elements with class .reveal start at opacity 0 and translateY(16px) and go to rest over 600ms when 15% visible, once (one shared IntersectionObserver in src/lib/reveal.ts adds .is-in). Siblings in a grid stagger by 70ms via a --i CSS variable (transition-delay calc(var(--i) * 70ms)). Elements already in the viewport on load reveal immediately with the same stagger.
- Motion: Card hover (treatment cards, team cards, plan cards, gallery tiles): translateY(-3px) and shadow card to lift over 200ms; gallery images also scale to 1.03 over 600ms inside their overflow-hidden tile.
- Motion: Open-now dot: an 8px Open circle with a ring that pulses (keyframes pulse-dot: box-shadow 0 0 0 0 rgba(47,125,91,0.45) to 0 0 0 8px rgba(47,125,91,0), 2000ms, infinite). When closed the dot is Slate and does not pulse.
- Motion: Accordions (FAQ, what-to-expect, mobile menu groups): height animates with the CSS grid trick (grid-template-rows 0fr to 1fr, inner overflow hidden) over 300ms; the lucide Plus icon rotates 45 degrees when open.
- Motion: Chips: day and slot chips scale to 0.97 on press; the selected state swaps background and text color over 200ms.
- Motion: Emergency banner dismiss: collapses height to 0 and fades over 250ms, then unmounts.
- Motion: Booking success: the form fades out (200ms), the success card fades in and rises 12px over 400ms, and the page scrolls so the card's top sits 96px below the viewport top.
- Motion: Reduced motion (prefers-reduced-motion: reduce): reveals show immediately with no transform, no stagger, no hover lift or image zoom, no dot pulse, accordions open and close instantly, smooth scrolling is replaced with instant jumps, the banner disappears without animation.
- Imagery: Real photographs of the clinic's rooms, furniture and equipment in soft daylight: sage walls, light white oak, cream upholstery, plants in terracotta. Never patients, never faces, never before/after mouths. Six photos are made for this template and hosted by its author; three CC0 photos (a quiet treatment-room lounge, handpieces on a dental unit, bamboo toothbrushes) add real-world detail. Photos are always shown in 24px-radius tiles with object-fit cover and the exact object-position given, never full-bleed behind text. People are shown as monogram avatars. Icons come from lucide-react; the favicon, wordmark glyph, the map, rating bars and decorative arches are drawn in SVG or CSS. No illustrations, no stock smiling-model photos, no 3D, no gradients other than the subtle ones specified.

## Pages & Sections
### Home (`index.html`)
1. **Shared: content file, data rules and head** — src/content.ts exports: brand, city, specialty, phone (display) and phoneHref ('tel:+13205550142'), email '[email protected]', address {line1 '218 Larkspur Avenue, Suite 2', line2 'Calder Springs', note 'Free parking behind the building · Bus 4 stops at Larkspur & 3rd'}, hours, treatments, categories, team, reviews, faqs, plans, images. Hours (one source for the table, open-now logic and slots): Mon 8:00–17:00, Tue 8:00–19:00, Wed 8:00–17:00, Thu 8:00–19:00, Fri 8:00–14:00, Sat 9:00–13:00, Sun closed; lunch break 12:30–13:30 Mon–Thu (no slots, but the clinic counts as open). Display times in 12-hour US format: '8:00 am', '5:00 pm'. Head: <title>Wrenfield Dental · Family & cosmetic dentistry in Calder Springs</title>. public/favicon.svg, viewBox 0 0 32 32: rect width 32 height 32 rx 9 fill #1F4A47; a tooth path fill #F7F4EE: 'M11 7.5c-2.9 0-4.7 2.3-4.7 5.4 0 2.6 1 4.6 1.8 6.9.8 2.3 1.1 6.2 2.8 6.2 1.6 0 1.8-3.5 2.5-5.3.4-1 1-1.5 2.6-1.5s2.2.5 2.6 1.5c.7 1.8.9 5.3 2.5 5.3 1.7 0 2-3.9 2.8-6.2.8-2.3 1.8-4.3 1.8-6.9 0-3.1-1.8-5.4-4.7-5.4-2.1 0-3.2 1.2-5 1.2s-2.9-1.2-5-1.2z'; a 3px circle at cx 23 cy 9 fill #BF4F35. The same tooth glyph (without the rounded square, fill Teal) is the 22px mark before the wordmark. This is an invented mark.
   Layout: All copy, numbers and image paths are read from src/content.ts; components contain no hard-coded strings. When the variable values change, rewrite every string in content.ts to fit the new practice (treatments, prices, credentials, FAQ, alt text) and keep the structure, counts and layout. Times are computed from the visitor's local clock, treated as the clinic's local time.
   Motion: None.
2. **Emergency banner (shared, top of both pages)** — lucide Siren 18px, then 'Toothache, swelling or a knocked-out tooth? We keep same-day emergency slots every weekday.' (under 768px shortened to 'Dental emergency? Same-day slots.'), then an underlined link 'Call (320) 555-0142' (tel:) and a close button (lucide X 18px, aria-label 'Dismiss emergency notice').
   Layout: Full width, Clay background, Linen text, Figtree 500 15px, height 44px (auto with 8px padding when wrapping), content centered in the container with 12px gaps; the close button sits at the right edge, 32px square. Not sticky: it scrolls away. Dismissal is saved in sessionStorage key 'banner-dismissed' and applies to both pages for the session.
   Motion: Collapse on dismiss as in Design motion.
3. **Navigation (shared)** — Left: tooth glyph + wordmark 'Wrenfield Dental' (Fraunces 600 21px, Teal), linking to ./index.html. Center links (≥1024px), Figtree 500 15px Ink, hover Teal with a 2px Clay underline that grows from the left: 'Treatments & prices' (./treatments.html), 'Team' (./index.html#team), 'Reviews' (./index.html#reviews), 'Insurance' (./index.html#insurance), 'Visit us' (./index.html#visit). The current page's link (Treatments on treatments.html) is Teal with the underline shown. Right: phone link with lucide Phone 16px '(320) 555-0142' (≥1280px only, Figtree 600 15px Teal) and the Clay primary button 'Book a visit' (44px tall) to ./index.html#book.
   Layout: Sticky top 0, z-index 40, height 76px (64px under 768px), background Linen at 92% with backdrop-blur 10px, 1px Line bottom border that only appears after scrollY > 8. Container 1200px, flex justify-between items-center. Under 1024px the center links hide and a 44px round button with lucide Menu 22px appears to the right of 'Book a visit' (which shrinks to 40px tall, label 'Book'); it opens MobileMenu: a full-width Paper panel dropping below the bar with the five links as 56px rows separated by Line, then a full-width Teal secondary button 'Call (320) 555-0142' and the hours line for today ('Today 8:00 am – 5:00 pm'). Escape, a link tap or the X icon closes it; body scroll locks while it is open.
   Motion: Menu panel opens with opacity 0 to 1 and translateY(-8px) to 0 over 300ms.
4. **Hero** — Eyebrow 'Family & cosmetic dentistry in Calder Springs'. H1 'Calm, careful dentistry for the <em>whole family.</em>'. Lead: 'Unhurried appointments, prices you can see before you sit down, and a team that explains every step. New patients welcome: kids, nervous adults and everyone in between.' Buttons: Clay primary 'Book a visit' (#book) and secondary 'See treatments & prices' (./treatments.html). Trust row under the buttons, Figtree 500 14px Slate, three items separated by 4px Line dots, each with a 16px lucide icon in Teal: Star (filled Clay) '4.9 from 418 patient reviews'; ShieldCheck 'In-network with most PPO plans'; Clock 'Open until 7:00 pm Tue & Thu'. Photo public/images/hero.webp (alt 'Bright treatment room with a cream dental chair, sage walls and a window with linen curtains'). Two floating cards over the photo: OpenNowCard at bottom-left: Open dot + 'Open now' (Figtree 700 15px Open) and 'Closes 5:00 pm today' (Slate 14px), or when closed a Slate dot + 'Closed now' and 'Opens Tue 8:00 am'; below a 1px Line and the address '218 Larkspur Avenue' with lucide MapPin 14px. Next-slot card at top-right: lucide CalendarCheck 18px Teal, 'Next free appointment' (Slate 13px) and the computed first available slot from src/lib/slots.ts, e.g. 'Tomorrow, 9:30 am' (Figtree 700 16px Teal; 'Tomorrow' when it is the next day, otherwise 'Thu 5 Nov'), linking to #book with that day and slot preselected.
   Layout: Linen background, padding 64px top, 96px bottom. Container grid 12 columns, gap 48px, items center. Text spans columns 1–6, max-width 580px. Photo spans columns 7–12 in a frame with aspect 4/5, radius 28px, overflow hidden, object-fit cover, object-position 55% 50%, loading eager, fetchpriority high. Behind the frame a decorative Sage 100 arch (a rounded-top rectangle, border-radius 999px 999px 28px 28px) offset 24px left and 24px down, z-index below the photo. OpenNowCard: Paper, radius 20px, padding 16px 20px, shadow lift, absolute left -32px bottom 40px, width 260px. Next-slot card: Paper, radius 20px, padding 14px 18px, shadow lift, absolute right 24px top 24px. Under 1024px: one column, text first, the photo full width with aspect 4/3 (object-position 55% 40%), the arch hidden, OpenNowCard moves inside the photo at left 16px bottom 16px, next-slot card at right 16px top 16px with the label hidden. H1 is 42px under 768px; buttons stack full width.
   Motion: Text block children reveal with --i 0–4 on load, the photo frame reveals with --i 2, the two cards with --i 5 and 6. The open dot pulses when open.
5. **Reassurance strip** — Four items, each a 48px Sage 100 circle with a 22px Teal lucide icon, an H3 at 17px and one Slate line: ShieldCheck 'Insurance, filed for you' — 'In-network with most PPO plans. We send the claim and show your share first.'; Wallet 'Payment plans at 0%' — 'Spread treatment over 6 or 12 months, no credit check under $2,000.'; Siren 'Same-day emergencies' — 'Slots held every weekday morning for pain, swelling and broken teeth.'; HandHeart 'Gentle by default' — 'Numbing gel before every injection, headphones, and a pause whenever you raise a hand.'
   Layout: Sage 50 background, padding 56px 0. Container grid 4 columns, gap 32px, each item a row: icon left, text right (gap 16px). Under 1024px 2 columns, under 640px 1 column with 24px gaps.
   Motion: Items reveal with --i 0–3.
6. **New-patient offer** — Image public/images/toothbrushes.jpg (alt 'Two bamboo toothbrushes on a woven bamboo mat'). Eyebrow 'New patients'. H2 'Your first visit: <em>$89,</em> everything included.' (from [NEW_PATIENT_OFFER]). Checklist with lucide CircleCheck 20px Open: 'A full exam with Dr. Marsh or Dr. Nandakumar', 'A professional cleaning and polish', 'Low-dose digital X-rays', 'A written treatment plan with prices, and no pressure to start anything'. Small print Slate 14px: 'Usually $240. Applies to patients paying without insurance. Most insured patients pay $0 for this visit.' Buttons: Clay primary 'Claim the $89 visit' (link ?treatment=new-patient#book) and a text link 'What happens at the first visit' (#faq, opens the FAQ item 'What happens at my first visit?').
   Layout: Linen background. Container, a single card: Paper, radius 28px, 1px Line border, overflow hidden, grid 2 columns (5fr 7fr). Left: the image filling the column, min-height 440px, object-fit cover, object-position 72% 70%. Right: padding 56px, flex column justify-center, checklist rows with 14px gaps. Top-right corner of the card a Clay 50 chip 'Save $151' (Figtree 700 13px Clay) at top 24px right 24px. Under 768px: one column, the image aspect 16/10 on top, padding 28px.
   Motion: Card reveals; checklist rows reveal with --i 0–3.
7. **Treatments preview** — Eyebrow 'Treatments'. H2 'Treatments, with the <em>price up front.</em>'. Lead 'Every price below is the range our patients actually pay before insurance. You get an exact written estimate before anything starts.' Six cards, each with a 40px Sage 100 icon circle (Teal lucide icon 20px), name (H3), one Slate line, a price row and a duration chip: Stethoscope 'New-patient visit' — 'Exam, cleaning and X-rays in one unhurried hour.' — '$89' — '60–75 min'; Sparkles 'Cleaning & check-up' — 'Twice a year keeps most problems small and cheap.' — '$145–$210' — '45 min'; Layers 'Tooth-colored fillings' — 'Matched to your tooth, done in one visit.' — '$160–$320 per tooth' — '30–60 min'; Sun 'Whitening' — 'In-chair in 90 minutes, or custom trays for home.' — '$280–$650' — '90 min'; Smile 'Clear aligners' — 'Straighter teeth with removable trays, planned with a 3D scan.' — '$3,400–$5,200' — '6–18 months'; Anchor 'Dental implants' — 'A permanent tooth replacement: post, abutment and crown.' — '$3,800–$4,900' — '3–6 months'. Each card ends with a Teal link 'Details' + ArrowRight 16px to ./treatments.html#t-<id> (ids new-patient, cleaning, fillings, whitening, aligners, implants). Below the grid a centered secondary button 'All 16 treatments & prices' to ./treatments.html.
   Layout: Linen background. Container grid 3 columns, gap 20px (2 columns under 1024px, 1 under 640px). Card: Paper, radius 24px, 1px Line border, padding 28px, flex column; the price row sits at the bottom (margin-top auto) with the price in Fraunces 500 28px Teal on the left and the duration chip on the right (Sage 50, Slate 13px Figtree 600, padding 6px 12px, lucide Clock 14px). The whole card is the link (one <a> wrapping it), focus ring 2px Clay offset 3px.
   Motion: Cards reveal with --i 0–5 and lift on hover; the ArrowRight moves 3px right on hover.
8. **Inside the clinic (gallery)** — Eyebrow 'The clinic'. H2 'A clinic that feels more like a <em>living room.</em>'. Lead 'Daylight in every treatment room, a ceiling screen to watch something during long visits, and a play corner by reception for brothers and sisters who come along.' Four tiles with a caption chip (Paper at 92%, radius 999px, Figtree 600 13px Teal, padding 8px 14px) at bottom-left 16px: A public/images/reception.webp 'Reception & waiting room' (alt 'Reception with an oak counter, a sage bench and plants'); B public/images/lounge.jpg 'Consult lounge' (alt 'Lounge with a tan sofa and a glass wall to a treatment room'); C public/images/kids-corner.webp 'Play corner' (alt 'Children's corner with a small oak table and picture books'); D public/images/instruments.jpg 'Sterilized every visit' (alt 'Handpieces on a dental unit beside a tray of instruments').
   Layout: Sage 50 background. Container grid 12 columns, two rows of 260px, gap 16px: A columns 1–6 rows 1–2; B columns 7–9 rows 1–2; C columns 10–12 row 1; D columns 10–12 row 2. Every tile radius 24px, overflow hidden, image object-fit cover. Exact crops: A object-position 50% 50%; B object-position 78% 50% (the crop must keep the left part of this photo, with its desk, out of view); C 50% 50%; D 40% 50%. Under 768px: a single column, A aspect 4/3, B aspect 4/5 (object-position 78% 50%), C aspect 1/1, D aspect 4/3. Images loading lazy.
   Motion: Tiles reveal with --i 0–3; image zoom on hover.
9. **Team (#team)** — Eyebrow 'Team'. H2 'The people <em>you'll see.</em>'. Lead 'Four clinicians, and the same faces at every visit. Here is who they are and what they trained in.' Four cards: (1) monogram 'HM', 'Dr. Helena Marsh', role 'Founder · General dentist', credentials list: 'DDS, 2008', '16 years in practice, 9 in Calder Springs', '600+ implants restored', 'Speaks English and Portuguese'; (2) 'TL', 'Dr. Theo Lindqvist', 'Cosmetic dentistry & aligners', 'DMD, 2014', 'Clear aligner provider since 2016', 'Porcelain veneers and bonding', 'Certified in nitrous oxide sedation'; (3) 'PN', 'Dr. Priya Nandakumar', 'Family & children's dentistry', 'DDS, 2012', 'Pediatric dentistry residency, 2 years', 'Sees patients from age 2', 'Gentle care for anxious patients'; (4) 'RD', 'Rosa Delgado, RDH', 'Lead dental hygienist', 'Registered dental hygienist, 2011', 'Deep cleaning and gum care', 'Local anesthesia certified', 'Known for very gentle cleanings'. Under the grid one Slate line: 'Questions about cost or insurance? Sam Okoro, our patient coordinator, answers weekdays 8:00 am – 5:00 pm.'
   Layout: Linen background. Container grid 4 columns, gap 20px (2 columns under 1024px, 1 under 640px). Card: Paper, radius 24px, 1px Line border, padding 28px. MonogramAvatar: 72px circle, Fraunces 500 26px Teal initials, letter-spacing 0.02em, background tints cycling Sage 100, Sage 300, Clay 50, Sage 100, with a 1px inner ring rgba(31,74,71,0.12). Below: name Fraunces 500 22px Teal, role Figtree 600 14px Slate, 1px Line, then the credentials as a list with lucide BadgeCheck 16px Open and Figtree 15px Ink, 10px gaps. No photos of people anywhere.
   Motion: Cards reveal with --i 0–3 and lift on hover.
10. **Reviews (#reviews)** — Eyebrow 'Reviews'. H2 'What patients say <em>after the visit.</em>'. Summary block: '4.9' (Fraunces 500 88px Teal), five Clay stars (lucide Star, filled, 20px), 'Average of 418 reviews from our patients' (Slate 15px), then five rating bars: 5 stars 92%, 4 stars 6%, 3 stars 1%, 2 stars 1%, 1 star 0% (label Figtree 600 13px, Sage 300 track 8px tall radius 999px, Teal fill to the percentage, percentage right in Slate 13px). Six review cards (5 stars unless noted): 'I hadn't been to a dentist in eleven years and was dreading it. Dr. Marsh showed me every X-ray, told me exactly what it would cost, and never once made me feel bad.' — Marcus T., new patient; 'Both kids now ask when they can go back. Dr. Nandakumar lets them hold the mirror and count their own teeth.' — Elena R., family of four; 'Cracked a molar on a Saturday morning, called at 9:10 and was in the chair by 11. The crown was done the following week.' — Owen B., emergency visit; 'The estimate said $1,240 after insurance and the bill said $1,240. That has never happened to me before.' — Priyanka S., crown; 'Rosa is the gentlest hygienist I have ever had. She stops before you even need to ask.' — Hannah L., cleaning; (4 stars) 'Evening slots fill fast, so book a couple of weeks ahead. Otherwise everything about my aligner treatment has been easy.' — Jordan K., clear aligners. Each card: stars 16px, the quote in Figtree 400 17px Ink, then name Figtree 700 15px Teal and treatment Slate 14px.
   Layout: Sage 50 background. Container grid 12 columns, gap 48px. Summary spans columns 1–4 and is sticky top 112px on ≥1024px. Cards span columns 5–12 in a CSS columns layout (column-count 2, column-gap 20px; cards break-inside avoid, margin-bottom 20px): Paper, radius 24px, 1px Line border, padding 28px; a Fraunces 400 64px Sage 300 opening quote mark sits at the top-left of each card, line-height 0.5. Under 1024px a single column, the summary first and not sticky, cards in 1 column.
   Motion: Summary reveals, rating bar fills animate from width 0 to their value over 800ms when visible (instant under reduced motion), cards reveal with --i 0–5.
11. **Insurance & payment plans (#insurance)** — Eyebrow 'Paying for care'. H2 'Insurance, memberships and <em>payment plans.</em>'. Lead 'Whichever way you pay, you see the number before we start.' Three cards: (1) lucide ShieldCheck 'Dental insurance' — 'We're in-network with most PPO plans and file every claim for you. Before treatment you get a written estimate of what your plan pays and what you pay.' rows: 'PPO plans' – 'In-network'; 'HMO / DHMO plans' – 'Call to check'; 'Out-of-network' – 'We file, you're reimbursed'. (2) lucide HeartHandshake 'Wrenfield Care Plan' — for patients without insurance: price '$29 / month' (Fraunces 500 40px) with 'or $319 a year · kids $19 / month' (Slate), checklist 'Two cleanings and exams a year', 'All routine X-rays', 'One emergency exam', '15% off every treatment'. Badge chip 'Most chosen without insurance' (Clay 50 background, Clay text) at top-right. (3) lucide CalendarRange 'Payment plans at 0%' — 'For treatment over $500. Split the cost into equal monthly payments with no interest.' rows: 'Terms' – '6 or 12 months'; 'Interest' – '0%'; 'Credit check' – 'None under $2,000'; 'Down payment' – '20%'. Below the cards a Teal text link 'Estimate your monthly payment' + ArrowRight to ./treatments.html#payment-plans.
   Layout: Linen background. Container grid 3 columns, gap 20px (1 column under 1024px). Cards: Paper, radius 24px, 1px Line border, padding 32px, flex column; the middle card has a 2px Teal border and Sage 50 background. Rows are definition pairs with a 1px Line top border, padding 12px 0, label Slate 15px left, value Figtree 600 15px Ink right. Do not name any insurance company.
   Motion: Cards reveal with --i 0–2 and lift on hover.
12. **Book & visit (#book, #visit)** — Eyebrow 'Book a visit'. H2 'Request an appointment <em>in a minute.</em>'. Lead 'Pick a time that suits you. We call or text within one business hour to confirm. Requests sent after hours are confirmed the next morning.' BookingForm card with four numbered steps (step number in a 28px Teal circle with Linen Figtree 700 14px digits, step title Figtree 700 17px Teal): 1 'What is the visit for?' — a select with options (value: label): new-patient: 'New-patient visit ($89)'; cleaning: 'Cleaning & check-up'; kids: 'Child's check-up'; emergency: 'Tooth pain or emergency'; whitening: 'Whitening consultation'; aligners: 'Clear aligner consultation (free)'; implants: 'Implant or crown consultation'; fillings: 'Fillings or other treatment'; other: 'Something else'. Default new-patient; if the URL has ?treatment=<value> (or a treatment id from treatments.html, mapped: crowns, root-canal and extraction to implants or fillings as listed in content.ts) it is preselected. Under it a segmented control 'I am a' with 'New patient' (default) and 'Returning patient'. When 'emergency' is selected, a Clay 50 notice appears under the select: lucide Siren in Clay, 'In pain right now? Calling is faster. We hold same-day emergency slots every weekday morning.' and a Clay button 'Call (320) 555-0142' (tel:). 2 'Choose a day' — DayStrip. 3 'Choose a time' — SlotPicker. 4 'Your details' — fields: 'Full name' (required), 'Mobile phone' (required, at least 10 digits), 'Email' (required, valid [email protected]), 'How will you pay?' select ('I have dental insurance', 'Wrenfield Care Plan member', 'Paying myself', 'Not sure yet'), 'Anything we should know? (optional)' textarea 3 rows with a live counter '0 / 300', and a checkbox 'Send me a text reminder the day before' (checked). Submit: Clay primary full-width button 'Request this appointment' with a summary line above it in Figtree 600 15px Teal: e.g. 'New-patient visit · Tue 3 Nov · 10:30 am' (or Slate 'Choose a day and time' when incomplete). Under the button Slate 13px: 'This sends a request, not a confirmed booking. We never share your details.' BookingSuccess: a 56px Open circle with a lucide Check 28px in Linen, H3 at 26px Fraunces 500 Teal 'Request received, Marcus.' (first word of the name), body 'We'll call you at (320) 555-0199 within one business hour to confirm your new-patient visit on Tuesday, 3 November at 10:30 am.' (all values from the form), a reference chip 'Reference WD-1030-03' (format WD-HHMM-DD from the chosen slot and day), a Sage 50 box with three lines 'Bring a photo ID and your insurance card', 'Arrive 10 minutes early for a short health form', 'Free parking behind the building', and two buttons: secondary 'Make another request' (resets the form) and a text link 'Back to top'. VisitPanel (right column) has three stacked cards: Hours card — 'Opening hours' title with the open-now status line (dot + 'Open now · closes 5:00 pm' or 'Closed · opens Tue 8:00 am'), HoursTable with seven rows Mon–Sun (day Figtree 600, hours right-aligned tabular-nums; Sun 'Closed' in Slate; lunch note under the table 'Closed for lunch 12:30–1:30 pm Mon–Thu' Slate 13px); today's row has Sage 50 background, radius 10px and a small 'Today' chip. Address card — MapDrawing on top, then '218 Larkspur Avenue, Suite 2', 'Calder Springs', the parking/bus note in Slate, phone link and email link with lucide Phone and Mail 16px. Emergency card — Clay 50 background, lucide Siren Clay, 'Dental emergency?' Figtree 700, 'Call before 10:00 am for a same-day slot. After hours, our message tells you who is on call.' and the phone as a Clay link.
   Layout: Sage 50 background, padding 112px 0. #visit anchor sits on the VisitPanel. Container grid 12 columns, gap 32px: the header spans 12 columns; the form card spans columns 1–7 (Paper, radius 28px, 1px Line, padding 40px, 28px under 768px; steps separated by 1px Line with 28px padding); VisitPanel spans columns 8–12 and is sticky top 104px on ≥1024px, cards Paper radius 24px padding 24px with 16px gaps. Under 1024px a single column with the form first. Fields: label Figtree 600 14px Ink above, input 52px tall, Paper background, 1px Line border, radius 14px, padding 0 16px, Figtree 16px; focus: border Teal and a 3px ring rgba(191,79,53,0.25); errors: border Clay, background Clay 50 and an error line in Clay Figtree 500 14px with lucide AlertCircle 14px ('Please enter your name', 'Enter a phone number with at least 10 digits', 'Enter a valid email', 'Choose a day', 'Choose a time'). Name and phone sit side by side ≥768px. Segmented control: Sage 50 track radius 999px padding 4px, two 40px options, selected option Paper with shadow card and Teal text. DayStrip: a horizontally scrollable row (scroll-snap x, hidden scrollbar, left/right 36px round arrow buttons with lucide ChevronLeft/ChevronRight on ≥768px) of the next 14 days starting tomorrow; each chip 64px wide × 76px tall, radius 18px, Paper with 1px Line border: weekday 'Tue' (Figtree 600 12px uppercase Slate), date '3' (Fraunces 500 24px Teal), month 'Nov' (Slate 12px). Sundays are disabled: Slate text at 50%, dashed border, label 'Closed' instead of the month. Selected chip: Teal background, Linen text, no border. The first open day is selected by default. SlotPicker: three groups 'Morning', 'Afternoon', 'Evening' (group label Figtree 600 13px uppercase Slate; a group with no slots is not rendered), chips in a wrapping flex row with 8px gaps, each 40px tall, min-width 92px, Paper with 1px Line border, Figtree 600 15px Ink, tabular-nums, label '10:30 am'. Slot rules in src/lib/slots.ts: start times every 30 minutes from opening until 30 minutes before closing; skip 12:30 pm and 1:00 pm Mon–Thu (lunch); a slot is shown as taken when (dayOfMonth * 3 + slotIndex * 7) % 6 === 0 (Slate at 45%, line-through, disabled, aria-label '10:30 am, taken'); groups: Morning before 12:00, Afternoon 12:00–16:59, Evening 17:00 and later. Selected slot: Teal background, Linen text. Changing the day clears the slot. Accessibility: the day strip and each slot group are radiogroups with arrow-key navigation, every input has a label, errors are linked with aria-describedby, the success card is in an aria-live polite region and receives focus. On submit: preventDefault, validate, focus and scroll to the first invalid field if any; otherwise show BookingSuccess in place of the form. Nothing is sent anywhere and nothing is stored. MapDrawing: inline SVG viewBox 0 0 400 220, radius 18px, background Linen; a grid of streets as 14px wide Paper rounded strokes on a Sage 50 field (two horizontal streets at y 70 and 160, three vertical at x 90, 210, 330, one diagonal from 0,220 to 140,0), a Sage 300 park rectangle (rx 12) between x 230–310 and y 90–140, a 6px Sage 300 river curve along the bottom, street labels in Figtree 600 10px Slate ('Larkspur Ave' along y 70, '3rd St' along x 210), the clinic pin at 210,70: a Clay teardrop 28px with a Linen 8px circle, and a small Teal 'P' parking square at 250,40. No map tiles, no external map service.
   Motion: Form steps reveal with --i 0–3; the emergency notice expands with the grid-rows trick; chip selection as in Design motion; the success swap as in Design motion. The VisitPanel cards reveal with --i 0–2.
13. **FAQ (#faq)** — Eyebrow 'FAQ'. H2 'Honest answers about <em>pain and cost.</em>'. Left side under the heading: Slate line 'Still unsure? Call (320) 555-0142 and ask for Sam. No question is too small.' Eight questions, the first open by default: 'Will it hurt?' — 'Most visits don't. Cleanings can feel scratchy, never sharp. Before any injection we numb the gum with a gel first, and we wait until you're fully numb before starting. You can raise a hand at any time and we stop.'; 'I haven't been to a dentist in years. Will I be judged?' — 'Never. About one in five of our new patients hasn't been in over five years. We start with a look and a conversation, then agree on a plan at your pace.'; 'What happens at my first visit?' — 'About an hour: a short health form, low-dose digital X-rays, a full exam, a cleaning and a written plan with prices. For patients paying themselves the visit is $89, and you're never asked to start treatment on the same day.'; 'How much will treatment cost me?' — 'The price ranges on our treatments page are what patients actually pay before insurance. Before any treatment you get a written estimate with the exact amount and your insurance share. The estimate is the price.'; 'Do you take my insurance?' — 'We're in-network with most PPO plans and can file out-of-network claims for most others. Send us your plan name and member ID and Sam will check your benefits before your visit.'; 'What if I don't have insurance?' — 'Choose the Wrenfield Care Plan at $29 a month for two cleanings, exams, X-rays, an emergency exam and 15% off treatment, or pay per visit at the listed prices.'; 'How do payment plans work?' — 'For treatment over $500 you pay 20% on the day and the rest in 6 or 12 equal monthly payments with no interest. There is no credit check for amounts under $2,000.'; 'What counts as a dental emergency?' — 'Severe toothache, swelling in your face or gums, a knocked-out or broken tooth, or bleeding that won't stop. Call us before 10:00 am for a same-day slot. If your face is swelling and you have trouble breathing or swallowing, go to the emergency room.'
   Layout: Linen background. Container grid 12 columns, gap 48px: heading block spans columns 1–4, sticky top 112px on ≥1024px; the accordion spans columns 6–12. Each item: 1px Line top border (and one at the bottom of the list), a full-width button with the question in Fraunces 500 21px Teal on the left and a 36px Sage 50 circle with lucide Plus 18px on the right, padding 22px 0; answer Figtree 17px Ink at 85%, max-width 62ch, padding-bottom 24px. Several items may be open at once. Buttons have aria-expanded and aria-controls. Links that target an FAQ item (the offer's 'What happens at the first visit') open it and scroll to it. Under 1024px one column, the heading not sticky.
   Motion: Accordion as in Design motion; items reveal with --i 0–7.
14. **Footer (shared)** — Column 1: tooth glyph (Linen) + 'Wrenfield Dental' (Fraunces 600 22px Linen), the line 'Family & cosmetic dentistry in Calder Springs since 2017.' and a Clay primary button 'Book a visit' (./index.html#book). Column 2 'Visit': '218 Larkspur Avenue, Suite 2', 'Calder Springs', 'Free parking behind the building'. Column 3 'Hours': compact rows 'Mon, Wed 8:00 am – 5:00 pm', 'Tue, Thu 8:00 am – 7:00 pm', 'Fri 8:00 am – 2:00 pm', 'Sat 9:00 am – 1:00 pm', 'Sun Closed'. Column 4 'Clinic': links 'Treatments & prices' (./treatments.html), 'Team' (./index.html#team), 'Reviews' (./index.html#reviews), 'Insurance' (./index.html#insurance), 'FAQ' (./index.html#faq), plus the phone and email links. Bottom row: '© Wrenfield Dental. Prices are typical ranges before insurance; your written estimate is final.' and, if [CREDIT] is kept, a small 'Template by VibeFather' link on the right.
   Layout: Teal background, Linen text, padding 88px 0 0. Container grid 4 columns (2fr 1fr 1fr 1fr), gap 40px; column titles Figtree 700 13px uppercase letter-spacing 0.12em Linen at 60%; items Figtree 15px Linen at 88%, links underline on hover. Bottom row: Teal 700 background, margin-top 64px, padding 20px 0, Figtree 13px Linen at 65%, flex justify-between, wraps under 768px. Under 1024px 2 columns, under 640px 1 column. A decorative Sage 300 arch at 8% opacity, 420px wide, sits at the right edge cropped by the bottom.
   Motion: None beyond link hovers.

### Treatments & prices (`treatments.html`)
1. **Shared chrome** — Emergency banner, navigation (with 'Treatments & prices' marked current) and footer exactly as on index.html. All links back to the home page use ./index.html#<anchor>; booking links use ./index.html?treatment=<id>#book. On load of index.html with ?treatment= present, the booking select is preset and, if the hash is #book, the page scrolls to #book after layout.
   Layout: Same components as the home page.
   Motion: Same as the home page.
2. **Treatments header** — Breadcrumb Figtree 500 14px Slate: 'Home' (./index.html) / 'Treatments & prices'. Eyebrow 'Treatments & prices'. H1 'Every treatment, with the <em>price in plain sight.</em>' Lead 'These are the ranges our patients actually pay before insurance, including X-rays and a follow-up check. Your written estimate before treatment is the final price.' Buttons: Clay 'Book a visit' (./index.html#book) and secondary 'Call (320) 555-0142' (tel:). Photo public/images/treatment-wide.webp (alt 'Wide view of a sage treatment room with a cream dental chair and a large window').
   Layout: Linen background, padding 56px 0 72px. Container grid 12 columns, gap 48px, items center: text columns 1–6, photo columns 7–12 in a frame with aspect 4/3, radius 28px, object-fit cover, object-position 40% 50%, loading eager. A Sage 100 arch behind the frame offset 24px right and 24px down. Under 1024px one column, photo aspect 16/10 below the text.
   Motion: Text children reveal with --i 0–4, photo with --i 2.
3. **Price promise strip** — Three items with Teal lucide icons in 44px Sage 100 circles: FileText 'Written estimate first' — 'You see the exact amount and your insurance share before we start.'; Receipt 'X-rays and follow-up included' — 'No separate charge for the images or the check after treatment.'; BadgeDollarSign 'No surprise fees' — 'If something changes mid-treatment, we stop and ask first.'
   Layout: Sage 50 band, padding 40px 0, container grid 3 columns, gap 32px, each item icon left and text right; 1 column under 768px.
   Motion: Items reveal with --i 0–2.
4. **Category navigation** — Five pill links with counts: 'Preventive 5' (#preventive), 'Restorative 5' (#restorative), 'Cosmetic 3' (#cosmetic), 'Orthodontics 2' (#orthodontics), 'Emergency 1' (#emergency). Count in a small 22px circle inside the pill.
   Layout: Sticky below the nav (top 76px, 64px under 768px), z-index 30, Linen at 92% with backdrop-blur 10px, 1px Line bottom border, height 64px. Pills: 40px tall, padding 0 16px, Figtree 600 15px, Paper with 1px Line border, Teal text; active pill Teal background, Linen text. On mobile the row scrolls horizontally with scroll-snap and the active pill scrolls into view. Scroll-spy: an IntersectionObserver (rootMargin '-45% 0px -50% 0px') sets the active pill to the category section crossing the middle of the viewport. Clicking a pill scrolls so the category heading sits 24px below the sticky bar (scroll-margin-top 164px on each category section).
   Motion: Active pill colors change over 200ms.
5. **Treatment categories (#preventive, #restorative, #cosmetic, #orthodontics, #emergency)** — Each category: lucide icon in a 52px Sage 100 circle, H2 name, a Slate description, and an insurance note chip. Preventive (ShieldPlus) — 'Keep small problems small. Most plans cover these at 80–100%.' chip 'Usually covered'. Rows: #t-new-patient 'New-patient visit' — 'Exam, cleaning, low-dose digital X-rays and a written plan.' — '$89' (unit 'first visit') — 60–75 min, 1 visit — expect: 'Short health form and a chat about any worries', 'X-rays and a full exam, shown to you on screen', 'Cleaning and polish, then your written plan'. #t-cleaning 'Cleaning & check-up' — 'Plaque and tartar removed, gums checked, teeth polished.' — '$145–$210' — 45 min, 1 visit — 'Gum measurements and a quick exam', 'Scaling and polishing by our hygienist', 'Advice on brushing spots you miss'. #t-kids 'Child's check-up' — 'For ages 2 to 13: a gentle look, a clean and fluoride.' — '$75–$120' — 30 min — 'Your child meets the chair and the mirror first', 'Counting teeth, a gentle clean and fluoride', 'A sticker and tips for parents'. #t-deep-cleaning 'Deep cleaning' — 'Cleaning below the gumline for early gum disease.' — '$220–$320' (unit 'per quarter of the mouth') — 60 min, 2 visits — 'Numbing gel and local anesthetic so you feel pressure, not pain', 'Roots smoothed so gums can reattach', 'A re-check after 6 weeks'. #t-night-guard 'Night guard' — 'A custom guard for clenching and grinding.' — '$380–$520' — 2 visits of 20 min — 'A quick 3D scan, no goopy impressions', 'Fitting visit two weeks later', 'Free adjustment in the first year'. Restorative (Wrench) — 'Repairs that look like your own teeth. Plans typically cover 50–80%.' chip 'Partly covered'. Rows: #t-fillings 'Tooth-colored filling' — 'Decay removed and the tooth rebuilt in matched resin.' — '$160–$320' ('per tooth') — 30–60 min — 'Numbing, then the decay is removed', 'Resin shaded to your tooth and hardened with light', 'Bite checked and polished'; #t-root-canal 'Root canal' — 'Saves an infected tooth instead of removing it.' — '$950–$1,400' ('molar') — 90 min, 1–2 visits — 'Full numbing; most patients say it feels like a long filling', 'Infection cleaned out and the canals sealed', 'A crown is usually advised afterwards'; #t-crowns 'Ceramic crown' — 'A full cover for a cracked or heavily filled tooth.' — '$1,150–$1,550' — 2 visits — 'Tooth shaped and scanned', 'Temporary crown for about two weeks', 'Final ceramic crown bonded in place'; #t-implants 'Dental implant' — 'A titanium post, abutment and ceramic crown for a missing tooth.' — '$3,800–$4,900' — 3–6 months — 'CT scan and planning visit', 'Post placed under local anesthetic', 'Crown fitted once the bone has healed'; #t-extraction 'Tooth removal' — 'Simple extraction when a tooth can't be saved.' — '$180–$350' — 30 min — 'Numbing and gentle loosening', 'Gauze, aftercare sheet and a call the next day', 'Options to replace the tooth later'. Cosmetic (Sparkles) — 'Changes to color and shape. Rarely covered by insurance; payment plans apply.' chip 'Rarely covered'. Rows: #t-whitening 'Whitening' — 'In-chair whitening in one visit, or custom trays for home.' — '$280–$650' (unit 'trays $280–$340 · in-chair $450–$650') — 90 min — 'Shade measured before and after', 'Gums protected, gel applied in three rounds', 'Sensitivity gel to take home'; #t-bonding 'Bonding' — 'Chips and gaps reshaped with resin in one visit.' — '$250–$480' ('per tooth') — 45–60 min — 'No numbing needed in most cases', 'Resin sculpted and hardened', 'Polished to match your enamel'; #t-veneers 'Porcelain veneers' — 'Thin porcelain shells for shape, size and color.' — '$1,100–$1,600' ('per tooth') — 3 visits — 'Smile design and a preview in temporary resin', 'Teeth prepared and scanned', 'Veneers bonded and the bite adjusted'. Orthodontics (Smile) — 'Straightening for teens and adults. Some plans cover up to $1,500 for under-19s.' chip 'Sometimes covered'. Rows: #t-aligners 'Clear aligners' — 'Removable trays, changed every two weeks, planned with a 3D scan.' — '$3,400–$5,200' — 6–18 months — 'Free consultation and 3D scan', 'See your planned result before you decide', 'Check-ins every 8 weeks'; #t-retainers 'Retainers' — 'Keeps teeth where they are after orthodontics.' — '$220–$450' ('pair') — 2 visits — 'Scan after treatment ends', 'Clear or bonded retainer fitted', 'Wear at night, checked at cleanings'. Emergency (Siren) — 'Pain, swelling or a broken tooth. Same-day slots every weekday.' chip 'Usually covered'. Row: #t-emergency 'Emergency exam' — 'Diagnosis, X-ray and pain relief the same day.' — '$120' ('flat, X-ray included') — 30 min — 'Call before 10:00 am for a same-day slot', 'X-ray and a clear explanation of options', 'Pain relieved before you leave, treatment planned'.
   Layout: Linen background. Each category section: padding 72px 0, 1px Line top border; container grid 12 columns, gap 48px. Left: columns 1–4, sticky top 164px on ≥1024px, holding the icon circle, the H2 (Fraunces 500 36px), the description (Slate 17px) and the insurance chip (Sage 50 background, Figtree 600 13px, Open text for 'Usually covered', Teal for 'Partly covered' and 'Sometimes covered', Slate for 'Rarely covered'). Right: columns 5–12, a stack of TreatmentRow cards with 12px gaps. TreatmentRow: Paper, radius 20px, 1px Line border, padding 24px 28px, grid 2 columns (1fr auto), gap 24px. Left: name Figtree 700 19px Teal, description Slate 16px, then meta chips (Sage 50, Slate 13px Figtree 600, radius 999px, padding 5px 12px, lucide Clock or CalendarDays 14px) for duration and visits. Right, top-aligned and right-aligned: price Fraunces 500 30px Teal tabular-nums, unit line Slate 13px below. Bottom of the card, spanning both columns, a row with a toggle button 'What to expect' (Figtree 600 14px Teal, lucide ChevronDown 16px that rotates 180° when open) on the left and a Teal link 'Book this' + ArrowRight 16px on the right (./index.html?treatment=<booking reason id>#book). The expanded panel shows the three steps as a numbered list with 22px Sage 100 number circles. Each row has id t-<id> and scroll-margin-top 164px; when the page loads with a matching hash, that row is opened and gets a 2px Clay outline that fades out over 1600ms. Under 1024px a single column; the category intro is not sticky; in each row the price moves under the name.
   Motion: Category intros reveal; rows reveal with --i by index; the expect panel uses the grid-rows accordion; rows lift slightly on hover (translateY(-2px)).
6. **Clear aligner feature** — Image public/images/aligners.webp (alt 'Clear aligner trays beside a sage case on an oak table'). Eyebrow 'Most asked about'. H2 'Clear aligners, planned <em>in one visit.</em>' Lead 'A free consultation includes a 3D scan of your teeth and a preview of where they will move, so you know the result, the number of months and the price before you decide.' Stats row of three: '$3,400–$5,200' / 'full treatment'; 'from $227' / 'per month on a 12-month plan, after 20% down'; '6–18 months' / 'typical length'. Checklist with lucide CircleCheck Open: 'Free consultation and 3D scan', 'Refinement trays included at no extra cost', 'First pair of retainers included'. Clay button 'Book a free aligner consult' (./index.html?treatment=aligners#book).
   Layout: Sage 50 background, padding 96px 0. Container grid 12 columns, gap 48px, items center: image columns 1–6 in a frame aspect 4/3, radius 28px, object-fit cover, object-position 65% 50%; text columns 7–12. Stats: 3 columns separated by 1px Line vertical rules, value Fraunces 500 30px Teal, label Slate 14px. Under 1024px one column, image first.
   Motion: Image and text reveal, stats with --i 0–2.
7. **Payment plan calculator (#payment-plans)** — Image public/images/consult.webp (alt 'Consultation desk with a model of teeth and two sage chairs'). Eyebrow 'Payment plans'. H2 'See your monthly payment <em>before you book.</em>' Calculator card: (1) 'Treatment' select listing every treatment whose upper price is at least $500, with its midpoint as the default amount (e.g. 'Ceramic crown · $1,350'), plus 'Custom amount'; (2) 'Treatment cost' range slider $500 to $6,000, step $50, with the value shown above the thumb in Fraunces 500 40px Teal ('$1,350'); moving the slider switches the select to 'Custom amount'; (3) 'Plan length' segmented control '6 months' / '12 months' (default 12). Results: 'Due on the day (20%)' = round(amount × 0.2); 'Then per month' = ceil((amount − due today) / months), shown in Fraunces 500 56px Teal with '/ month'; 'Total' = amount, 'Interest' '0%'. A note line: amounts up to $2,000 show 'No credit check needed' with lucide CircleCheck in Open; above $2,000 'A soft credit check that doesn't affect your score' in Slate. Buttons: Clay 'Book a visit' (./index.html#book) and a Teal text link 'Ask Sam about your insurance' (tel:). Default state: Ceramic crown, $1,350, 12 months gives $270 today and $90 per month.
   Layout: Linen background, padding 96px 0. Container grid 12 columns, gap 48px: left columns 1–5 holds the heading block and the image below it (aspect 4/3, radius 24px, object-fit cover, object-position 50% 55%); right columns 6–12 holds the calculator card: Paper, radius 28px, 1px Line, padding 40px. Results area: Sage 50 box radius 20px padding 24px, rows separated by 1px Line. Slider: 6px Sage 300 track with a Teal fill to the thumb, 24px Paper thumb with a 2px Teal border and shadow card, keyboard accessible (native input type range styled). Under 1024px one column, the calculator before the image.
   Motion: Result numbers update instantly; the monthly value briefly scales from 0.98 to 1 over 200ms on change (not under reduced motion).
8. **Closing call-to-action** — H2 (Linen) 'Not sure what you'll <em>pay?</em>' Lead (Linen at 80%) 'Send a booking request or call, and we'll check your insurance and reply with an estimate within one business day.' Buttons: Clay 'Book a visit' (./index.html#book) and a Linen-outlined secondary 'Call (320) 555-0142' (1.5px Linen border, Linen text, hover background rgba(247,244,238,0.1)). Right side: OpenNowCard (same component as the hero, Paper).
   Layout: Container, a Teal panel radius 28px, padding 64px, grid 2 columns (7fr 5fr), items center, overflow hidden; a decorative Sage 300 arch at 14% opacity, 360px wide, anchored to the bottom-right inside the panel. Under 768px one column, padding 32px, buttons full width. Margin 0 auto 112px.
   Motion: Panel reveals.

## Assets
- 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/b79d3426-5243-4ac1-9cd0-6b60aa93ace6/hero.webp → public/images/hero.webp (Home hero; alt 'Bright treatment room with a cream dental chair, sage walls and a window with linen curtains'); https://media.vibefather.ai/assets/b79d3426-5243-4ac1-9cd0-6b60aa93ace6/reception.webp → public/images/reception.webp (Gallery tile A; alt 'Reception with an oak counter, a sage bench and plants'); https://media.vibefather.ai/assets/b79d3426-5243-4ac1-9cd0-6b60aa93ace6/kids-corner.webp → public/images/kids-corner.webp (Gallery tile C; alt 'Children's corner with a small oak table and picture books'); https://media.vibefather.ai/assets/b79d3426-5243-4ac1-9cd0-6b60aa93ace6/treatment-wide.webp → public/images/treatment-wide.webp (Treatments header; alt 'Wide view of a sage treatment room with a cream dental chair and a large window'); https://media.vibefather.ai/assets/b79d3426-5243-4ac1-9cd0-6b60aa93ace6/aligners.webp → public/images/aligners.webp (Clear aligner feature; alt 'Clear aligner trays beside a sage case on an oak table'); https://media.vibefather.ai/assets/b79d3426-5243-4ac1-9cd0-6b60aa93ace6/consult.webp → public/images/consult.webp (Payment plan calculator; alt 'Consultation desk with a model of teeth and two sage chairs').
- image: CC0 photo: https://pd.w.org/2026/01/473697e76686ae8d2.18620605-2048x1365.jpg → public/images/lounge.jpg. Gallery tile B, a treatment-room lounge with a tan sofa, arc lamp and glass wall. Always crop with object-position 78% 50% in a portrait tile so the desk at the left of the photo stays out of view. Source page https://wordpress.org/photos/photo/473697e766/, author Kevin Baharvand (WordPress Photo Directory), license CC0 1.0.
- image: CC0 photo: https://pd.w.org/2026/04/67469efbf72491a05.40591059-2048x1536.jpg → public/images/instruments.jpg. Gallery tile D, dental handpieces on a unit beside an instrument tray. Source page https://wordpress.org/photos/photo/67469efbf7/, author Nilo Velez (WordPress Photo Directory), license CC0 1.0.
- image: CC0 photo: https://pd.w.org/2023/03/574641d8aa020bb64.64728093-1536x1536.jpg → public/images/toothbrushes.jpg. New-patient offer image, two bamboo toothbrushes on a bamboo mat (object-position 72% 70%). Source page https://wordpress.org/photos/photo/574641d8aa/, author Nora Ferreirós (WordPress Photo Directory), license CC0 1.0.
- image: Write ASSETS.md at the project root with a table: path, source URL, author, license, for all nine images (the six template photos list source 'media.vibefather.ai, made for this template', author 'VibeFather', license 'Distributed with the template'), plus the two font packages and lucide-react with their licenses. If you change [SPECIALTY], replace the six template photos with photos of your own rooms in the same style (daylight, sage, oak, no people) and swap any CC0 photo that no longer fits for another CC0 or public-domain photo with the same rules.
- icon: lucide-react only: Siren, X, Menu, Phone, Mail, MapPin, Clock, Star, ShieldCheck, ShieldPlus, Wallet, HandHeart, HeartHandshake, CalendarRange, CalendarCheck, CalendarDays, Stethoscope, Sparkles, Layers, Sun, Smile, Anchor, Wrench, BadgeCheck, CircleCheck, Check, AlertCircle, ArrowRight, ChevronDown, ChevronLeft, ChevronRight, Plus, FileText, Receipt, BadgeDollarSign. Stroke width 1.75, sizes as specified. If an icon name is missing in the installed version, use the closest lucide icon. No emoji.
- icon: public/favicon.svg and the tooth glyph before the wordmark are hand-written SVG as described in the shared head section. The brand itself is text in Fraunces; there is no other logo.
- font: Install @fontsource-variable/fraunces and @fontsource-variable/figtree and import them in both entry files. Vite bundles the woff2 files into dist/.
- image: Drawn in code: the map (inline SVG), monogram avatars, rating bars, decorative arches, the day strip and slot chips. No other bitmaps.

## Don'ts
- No backend of any kind: no server code, API routes, databases, auth, payments, email services, analytics or third-party APIs. The booking form calls preventDefault, validates in the browser and only swaps to the success state; it never submits, sends or stores anything.
- No map embeds or map tile services; the map is the inline SVG described.
- 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 './'). The site is two real HTML files; every internal link points to ./index.html, ./treatments.html or a hash on them, never to a bare directory or /.
- Do not change the stack (Vite 5 + React 18 + TypeScript + Tailwind CSS 3.4 + lucide-react + Fontsource) unless the user asks. No animation library, no UI kit, no router: two entries and hash anchors.
- No real clinic's name, logo, slogan or copy, and no real dentists' names or credentials. All clinicians, patients, reviews, prices and the address are invented.
- No photos or illustrations of people: no faces, no patients, no before/after mouths, no stock smiling models. Team members appear only as monogram avatars.
- No real insurance companies, dental brands, equipment makers or product names anywhere in copy or images. Describe insurance only as PPO, HMO / DHMO and out-of-network.
- No medical claims beyond what is written here: no guarantees, no 'painless', no success-rate numbers. Keep the advice to go to the emergency room for swelling with trouble breathing or swallowing.
- Only the listed images, with the exact crops given (lounge.jpg always at object-position 78% 50% so its left side stays hidden). No Unsplash, Pexels, Pixabay or other stock sites with their own licenses, no placeholder-image services.
- Clay is the only accent and is reserved for booking buttons, the emergency banner and notices, stars, the map pin and the focus ring. No other bright colors, no blue medical gradients, no glassmorphism, no dark mode.
- No commercial or custom fonts: only Fraunces and Figtree (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.
- Respect prefers-reduced-motion exactly as described under Design motion.
- Must render at 1440×900 and 390×844 with zero console errors and no horizontal page scroll (only the day strip and the mobile category pills scroll inside themselves). Every interactive element is keyboard reachable with a visible Clay focus ring.
- Keep dist/ under 20 MB (target under 8 MB).
- No lorem ipsum, filler or hype words. Use the exact headlines, prices, hours and CTAs given here for the default values. No meta descriptions, Open Graph tags, JSON-LD or sitemap: only the <title> and favicon.

---
— Prompt by VibeFather · https://vibefather.ai/t/dental-clinic-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: "Dental Clinic Website"
colors:
  linen: "#F7F4EE"
  paper: "#FFFFFF"
  sage_50: "#EEF3EF"
  sage_100: "#DFE8E1"
  sage_300: "#B7CBBE"
  teal: "#1F4A47"
  teal_700: "#163634"
  ink: "#1C2624"
  slate: "#5B6966"
  line: "#DCE3DD"
  clay: "#BF4F35"
  clay_700: "#A3412A"
  clay_50: "#FBEAE4"
  open: "#2F7D5B"
typography:
  display_h1_h2_prices_big_rating_number_monograms_wordmark: { family: "Fraunces Variable", weights: [400, 500, 600] }
  text_body_nav_buttons_labels_chips_form_fields_h3: { family: "Figtree Variable", weights: [400, 500, 600, 700] }
spacing: "8px base unit. Container max-width 1200px, side gutter clamp(20px, 4vw, 40px). Section vertical padding 112px on desktop, 72px under 768px. H1 Fraunces 500 clamp(42px, 5.4vw, 72px), line-height 1.04, letter-spacing -0.02em, color Teal. H2 Fraunces 500 clamp(32px, 3.6vw, 48px), line-height 1.1, letter-spacing -0.015em, Teal; one word or short phrase per H2 is set in Fraunces 400 italic (marked with <em> in the copy below). H3 Figtree 600 20px/1.3 Ink. Body Figtree 400 17px/1.65 Ink (16px under 768px); lead paragraphs 19px Slate. Eyebrows Figtree 600 13px uppercase, letter-spacing 0.12em, Teal at 80%, with a 6px Clay dot 10px before the text. Prices Fraunces 500 with font-variant-numeric tabular-nums. Section headers: eyebrow, H2 and a max-width 56ch lead, 48px below the header before content."
radius: "Cards and photo tiles 24px, the new-patient offer card and the booking form card 28px, inputs and select 14px, buttons, chips, the day strip chips and time-slot chips fully rounded (999px), icon circles and monogram avatars are circles. Primary buttons are 52px tall pills (44px in the nav), padding 0 26px, Figtree 600 16px, Clay background, Linen text, with a lucide ArrowRight 18px that moves 3px right on hover. Secondary buttons are the same size with a 1.5px Teal border, Teal text, transparent background, Sage 100 fill on hover."
---

# Dental Clinic 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
- **Linen** `#F7F4EE` — Page background, text on Teal and Clay surfaces
- **Paper** `#FFFFFF` — Cards, form surface, floating hero cards, inputs
- **Sage 50** `#EEF3EF` — Alternating section background (Reassurance, Team, Book & visit), chip backgrounds
- **Sage 100** `#DFE8E1` — Icon circles, monogram avatar tint A, selected day chip border, hover fill of ghost buttons
- **Sage 300** `#B7CBBE` — Monogram avatar tint B, rating bar track, map park areas, decorative arches
- **Teal** `#1F4A47` — Headings, wordmark, secondary buttons, selected chips, footer and closing CTA background
- **Teal 700** `#163634` — Teal button hover, footer bottom row
- **Ink** `#1C2624` — Body text on light surfaces
- **Slate** `#5B6966` — Secondary text, captions, field help, durations, unavailable slots
- **Line** `#DCE3DD` — 1px borders of cards, inputs, dividers, table rows
- **Clay** `#BF4F35` — The only accent: primary 'Book a visit' buttons, emergency banner background, star icons, focus ring, the map pin. Never used for large surfaces other than the banner.
- **Clay 700** `#A3412A` — Clay button hover and active
- **Clay 50** `#FBEAE4` — Emergency notice box in the booking form and side panel, error field background
- **Open** `#2F7D5B` — Open-now dot and text, success check, 'often covered' insurance chip text

## Typography
- **Display (H1, H2, prices, big rating number, monograms, wordmark)** — Fraunces Variable (OFL), weights 400/500/600. Self-host the font files.
- **Text (body, nav, buttons, labels, chips, form fields, H3)** — Figtree Variable (OFL), weights 400/500/600/700. Self-host the font files.

## Spacing & shape
- Spacing: 8px base unit. Container max-width 1200px, side gutter clamp(20px, 4vw, 40px). Section vertical padding 112px on desktop, 72px under 768px. H1 Fraunces 500 clamp(42px, 5.4vw, 72px), line-height 1.04, letter-spacing -0.02em, color Teal. H2 Fraunces 500 clamp(32px, 3.6vw, 48px), line-height 1.1, letter-spacing -0.015em, Teal; one word or short phrase per H2 is set in Fraunces 400 italic (marked with <em> in the copy below). H3 Figtree 600 20px/1.3 Ink. Body Figtree 400 17px/1.65 Ink (16px under 768px); lead paragraphs 19px Slate. Eyebrows Figtree 600 13px uppercase, letter-spacing 0.12em, Teal at 80%, with a 6px Clay dot 10px before the text. Prices Fraunces 500 with font-variant-numeric tabular-nums. Section headers: eyebrow, H2 and a max-width 56ch lead, 48px below the header before content.
- Radius: Cards and photo tiles 24px, the new-patient offer card and the booking form card 28px, inputs and select 14px, buttons, chips, the day strip chips and time-slot chips fully rounded (999px), icon circles and monogram avatars are circles. Primary buttons are 52px tall pills (44px in the nav), padding 0 26px, Figtree 600 16px, Clay background, Linen text, with a lucide ArrowRight 18px that moves 3px right on hover. Secondary buttons are the same size with a 1.5px Teal border, Teal text, transparent background, Sage 100 fill on hover.

## Motion
- Easing everywhere: cubic-bezier(0.22, 1, 0.36, 1). Durations: 200ms for hovers and chip selection, 300ms for accordions and menus, 600ms for reveals.
- Reveal: elements with class .reveal start at opacity 0 and translateY(16px) and go to rest over 600ms when 15% visible, once (one shared IntersectionObserver in src/lib/reveal.ts adds .is-in). Siblings in a grid stagger by 70ms via a --i CSS variable (transition-delay calc(var(--i) * 70ms)). Elements already in the viewport on load reveal immediately with the same stagger.
- Card hover (treatment cards, team cards, plan cards, gallery tiles): translateY(-3px) and shadow card to lift over 200ms; gallery images also scale to 1.03 over 600ms inside their overflow-hidden tile.
- Open-now dot: an 8px Open circle with a ring that pulses (keyframes pulse-dot: box-shadow 0 0 0 0 rgba(47,125,91,0.45) to 0 0 0 8px rgba(47,125,91,0), 2000ms, infinite). When closed the dot is Slate and does not pulse.
- Accordions (FAQ, what-to-expect, mobile menu groups): height animates with the CSS grid trick (grid-template-rows 0fr to 1fr, inner overflow hidden) over 300ms; the lucide Plus icon rotates 45 degrees when open.
- Chips: day and slot chips scale to 0.97 on press; the selected state swaps background and text color over 200ms.
- Emergency banner dismiss: collapses height to 0 and fades over 250ms, then unmounts.
- Booking success: the form fades out (200ms), the success card fades in and rises 12px over 400ms, and the page scrolls so the card's top sits 96px below the viewport top.
- Reduced motion (prefers-reduced-motion: reduce): reveals show immediately with no transform, no stagger, no hover lift or image zoom, no dot pulse, accordions open and close instantly, smooth scrolling is replaced with instant jumps, the banner disappears without animation.

## Imagery
Real photographs of the clinic's rooms, furniture and equipment in soft daylight: sage walls, light white oak, cream upholstery, plants in terracotta. Never patients, never faces, never before/after mouths. Six photos are made for this template and hosted by its author; three CC0 photos (a quiet treatment-room lounge, handpieces on a dental unit, bamboo toothbrushes) add real-world detail. Photos are always shown in 24px-radius tiles with object-fit cover and the exact object-position given, never full-bleed behind text. People are shown as monogram avatars. Icons come from lucide-react; the favicon, wordmark glyph, the map, rating bars and decorative arches are drawn in SVG or CSS. No illustrations, no stock smiling-model photos, no 3D, no gradients other than the subtle ones specified.

## Tone
Warm, plain and reassuring, like a good receptionist on the phone. Short sentences, real numbers, no jargon without a plain explanation, no fear tactics, no hype words (no world-class, state-of-the-art, cutting-edge, best-in-class, revolutionary). Address the reader as 'you'; the practice speaks as 'we'.

---
— Prompt by VibeFather · https://vibefather.ai/t/dental-clinic-website · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown