diff --git a/assets/diana_photo-min-1-scaled.webp b/assets/diana_photo-min-1-scaled.webp new file mode 100644 index 0000000..400b141 Binary files /dev/null and b/assets/diana_photo-min-1-scaled.webp differ diff --git a/specification/33-frontend-spec.md b/specification/33-frontend-spec.md new file mode 100644 index 0000000..ef70c0d --- /dev/null +++ b/specification/33-frontend-spec.md @@ -0,0 +1,1393 @@ +# 33 — Frontend Specification +## HER — Home Enhancement and Renovation + +**Version**: 1.0 +**Phase**: 3 — Themed Specification +**Status**: Implementation-ready +**Depends on**: `01-requirements.md`, `02-architecture-decisions.md` +**Referenced by**: `37-seo-content-spec.md`, `38-lead-capture-spec.md` + +--- + +## Table of Contents + +1. [Purpose & Scope](#1-purpose--scope) +2. [Design Tokens](#2-design-tokens) +3. [Responsive Breakpoints](#3-responsive-breakpoints) +4. [Navigation](#4-navigation) +5. [Page Specifications](#5-page-specifications) + - 5.1 [Home (`/`)](#51-home-) + - 5.2 [Services Hub (`/services/`)](#52-services-hub-services) + - 5.3 [Service Detail Template (`/services/[slug]/`)](#53-service-detail-template-servicesslug) + - 5.4 [About Diana (`/about/`)](#54-about-diana-about) + - 5.5 [Testimonials (`/testimonials/`)](#55-testimonials-testimonials) + - 5.6 [Contact / Request a Quote (`/contact/`)](#56-contact--request-a-quote-contact) +6. [Component Inventory](#6-component-inventory) +7. [Animation & Motion](#7-animation--motion) +8. [Image Treatment](#8-image-treatment) +9. [Accessibility](#9-accessibility) +10. [Requirements Traceability](#10-requirements-traceability) + +--- + +## 1. Purpose & Scope + +This document specifies the complete frontend design and layout for the HER static website. It is the authoritative reference for page structure, visual language, component behavior, and copy direction. It does not contain implementation code; it constrains and guides the implementation phase. + +**Site purpose**: Convert visitors into qualified quote requests through a credible, mobile-first, trustworthy presentation of Diana's handywoman services in the San Francisco Bay Area. + +**Primary user flows** (from `00-overview.md`): +1. Home → scans hero + services → taps "Request a Quote" → submits form. +2. Service page (organic search) → reads what's included → taps CTA → submits form. +3. About/Testimonials → validates trust → taps CTA → submits form. + +**Technology constraints**: Static HTML/CSS/JS output. No framework assumed. No CMS. Served behind Caddy. (ADR-001) + +--- + +## 2. Design Tokens + +All tokens are defined as CSS custom properties on `:root`. Token names are the canonical references throughout this spec. No hardcoded values appear in components. + +### 2.1 Color Tokens + +| Token | Value | Role | +|---|---|---| +| `--col-graphite` | `#252B30` | Headers, nav background, footer background, primary dark surface | +| `--col-linen` | `#F4F1EB` | Main page background, default section background | +| `--col-copper` | `#B5622A` | Primary CTA accent, HER wordmark, interactive highlights | +| `--col-copper-hover` | `#9A4E20` | Button/link hover state; darker variant of copper | +| `--col-slate` | `#5C7080` | Secondary text, metadata, tags, bylines | +| `--col-mist` | `#E8ECF0` | Alternating section backgrounds, card surfaces, service card fill | +| `--col-chalk` | `#EDEDEB` | Borders, dividers, horizontal rules | +| `--col-ink` | `#1A1A1A` | Body text, primary readable content | + +**Contrast compliance** (see §9 Accessibility): +- `--col-ink` on `--col-linen`: ≥ 12:1 — passes WCAG AA and AAA. +- `--col-graphite` on `--col-linen`: ≥ 9:1 — passes. +- `--col-copper` on `--col-linen`: Must be verified; use only for large text or decorative elements if contrast falls below 4.5:1. Copper buttons must have sufficient contrast between white label and `--col-copper` background (verify ≥ 3:1 for large button text). +- White text on `--col-graphite`: ≥ 10:1 — passes. +- White text on `--col-copper` CTA band: verify at implementation (white on `#B5622A` is approximately 3.0:1 — meets WCAG AA for large text at ≥ 24px or bold ≥ 18.67px; button label must be at least `--text-base` bold). + +### 2.2 Typography + +**Font loading**: Both fonts loaded from Google Fonts via a single `` preconnect + stylesheet in ``. Subset to Latin. `font-display: swap` on both. + +| Font | Source | Weights / Axes | Usage | +|---|---|---|---| +| **Fraunces** | Google Fonts, variable | `opsz` axis, weight 400; style: italic | Display only — H1, H2, hero headline, section headlines, pull quotes, HER wordmark | +| **DM Sans** | Google Fonts, variable | Weights 400, 500 | All other text: H3, H4, nav, buttons, body, labels, eyebrows, captions | + +**Usage rules**: +- Fraunces is **never** used at sizes smaller than `--text-xl` (22px). +- Fraunces is **always** set in italic (`font-style: italic`). +- DM Sans 400 = body, secondary text, form fields. +- DM Sans 500 = eyebrows, labels, buttons, utility text (uppercase, `letter-spacing: 0.08em`). +- Do not mix Fraunces and DM Sans on the same line of a heading. +- Line height for Fraunces headings: 1.1. +- Line height for DM Sans body: 1.6. +- Line height for DM Sans small/label: 1.4. + +**Eyebrow / Section tag style** (used across all pages): +- Font: DM Sans 500 +- Size: `--text-xs` +- Transform: `uppercase` +- Letter-spacing: `0.08em` +- Color: `--col-copper` +- No decorative marks above/below (no rules, no dots) — text only + +### 2.3 Type Scale + +| Token | rem | px | Role | +|---|---|---|---| +| `--text-xs` | 0.75rem | 12px | Captions, tags, card metadata | +| `--text-sm` | 0.875rem | 14px | Secondary body, form hints, breadcrumbs | +| `--text-base` | 1rem | 16px | Body copy, paragraph text | +| `--text-lg` | 1.125rem | 18px | Lead paragraph (first paragraph of section or page hero) | +| `--text-xl` | 1.375rem | 22px | H4, card headings | +| `--text-2xl` | 1.75rem | 28px | H3, subsection headings, HER wordmark in nav | +| `--text-3xl` | 2.25rem | 36px | H2, section headings (mobile) | +| `--text-4xl` | 3rem | 48px | H1 (mobile), pull quotes | +| `--text-5xl` | 4rem | 64px | H1 (desktop) | + +**Responsive heading rules**: +- H1 uses `--text-4xl` at mobile, steps up to `--text-5xl` at `lg` breakpoint. +- H2 uses `--text-3xl` at mobile, stays at `--text-3xl` (no change needed; already impactful). +- H3 uses `--text-2xl` at all breakpoints. +- H4 uses `--text-xl` at all breakpoints. + +### 2.4 Spacing Scale (8-point grid) + +| Token | rem | px | Common use | +|---|---|---|---| +| `--space-1` | 0.5rem | 8px | Icon gaps, inline padding, tight label spacing | +| `--space-2` | 1rem | 16px | Component internal padding, form field gap | +| `--space-3` | 1.5rem | 24px | Card padding, between stacked elements | +| `--space-4` | 2rem | 32px | Section sub-element spacing | +| `--space-6` | 3rem | 48px | Section top/bottom padding (mobile) | +| `--space-8` | 4rem | 64px | Section top/bottom padding (desktop), hero vertical rhythm | +| `--space-12` | 6rem | 96px | Large section separators, hero vertical padding (desktop) | +| `--space-16` | 8rem | 128px | Maximum-impact spacing (above fold hero only) | + +**Grid gutters**: `--space-3` (24px) horizontal gutter between columns in all grid layouts. + +### 2.5 Other Tokens + +| Token | Value | Role | +|---|---|---| +| `--radius-sm` | 4px | Input fields, tags, small elements | +| `--radius-md` | 8px | Cards, buttons | +| `--radius-lg` | 16px | Image containers, modals | +| `--shadow-card` | `0 2px 8px rgba(37,43,48,0.08)` | Service cards, testimonial cards, hover lift | +| `--shadow-card-hover` | `0 6px 20px rgba(37,43,48,0.13)` | Card hover state (elevated) | +| `--max-width` | 1160px | Maximum content width for all sections | +| `--nav-height` | 64px (mobile) / 72px (desktop) | Sticky nav height; used for scroll-offset calculations | + +--- + +## 3. Responsive Breakpoints + +| Breakpoint | Token | Min-width | Description | +|---|---|---|---| +| Mobile (default) | — | 0px | Base styles; single-column | +| Small | `sm` | 480px | Wider mobile; minor layout adjustments | +| Medium | `md` | 768px | Tablet; 2-column grids begin | +| Large | `lg` | 1024px | Desktop; 3-column grids, full nav | +| Extra large | `xl` | 1160px | Content width cap (`--max-width`) | + +All styles are written **mobile-first**: base styles target mobile, breakpoints progressively enhance for larger screens. + +--- + +## 4. Navigation + +The navigation bar appears at the top of every page and is **sticky** (fixed to the top on scroll). It has two states: **default** and **scroll-compact**. + +### 4.1 Mobile Navigation (below `lg`) + +**Default state** (top of page): + +``` +┌─────────────────────────────────────────┐ +│ HER (italic copper) [☎] [☰] │ height: 64px +└─────────────────────────────────────────┘ +``` + +- **Left**: "HER" wordmark — Fraunces italic, `--text-2xl`, `--col-copper`. +- **Center-right**: Phone icon — inline SVG phone handset, `--col-graphite`; links to `tel:` URI (click-to-call). Minimum 44×44px touch target. +- **Right**: Hamburger icon — 3 horizontal lines, `--col-graphite`. Minimum 44×44px touch target. Opens mobile menu overlay. +- Background: `--col-graphite`. +- Logo links to `/`. + +**Scroll-compact state** (after scrolling down ≥ 80px): +- Nav height smoothly transitions to 52px. +- Wordmark + phone icon + hamburger remain visible; no layout change otherwise. +- Transition: `height 200ms ease`, `background-color 200ms ease` (if background opacity is modified). +- On scroll-up ≥ 20px: return to default height. + +**Mobile menu overlay** (hamburger pressed): +- Full-screen overlay, `--col-graphite` background, slides down from top (transform: translateY, 250ms ease-out). +- Close button (×) top-right, same position as hamburger. +- Links stacked vertically, centered, `--text-2xl`, DM Sans 400, `--col-linen`, with `--space-6` between items: + - About + - Services + - Testimonials + - Contact + - Request a Quote (copper button, full-width) +- Phone number and email displayed at the bottom of the overlay, `--col-slate`, `--text-sm`. +- Pressing any link or the close button dismisses the overlay. +- Focus trap: keyboard focus must cycle within the overlay while it is open. +- `aria-expanded` on the hamburger button reflects open/closed state. + +### 4.2 Desktop Navigation (at `lg` and above) + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ HER (italic copper) About Services Testimonials Contact [Request a Quote] │ height: 72px +└────────────────────────────────────────────────────────────────────┘ +``` + +- **Left**: "HER" wordmark — Fraunces italic, `--text-2xl`, `--col-copper`. Links to `/`. +- **Center**: Nav links — DM Sans 500, `--text-sm`, uppercase, letter-spacing 0.08em, `--col-linen`. Active page link: `--col-copper`. Hover: `--col-copper`. Gap between links: `--space-4`. +- **Right**: "Request a Quote" button — primary button (copper), `--text-sm`, DM Sans 500, `--radius-md`. +- Background: `--col-graphite`. +- Content width constrained to `--max-width`, centered. +- Nav links: About (`/about/`), Services (`/services/`), Testimonials (`/testimonials/`), Contact (`/contact/`). + +**Scroll-compact state** (desktop): +- Height transitions from 72px to 60px. +- Logo scales slightly smaller (transform: scale(0.9)). +- All links remain visible. + +### 4.3 Nav Accessibility + +- `