diff --git a/docs/memory/component-registry.md b/docs/memory/component-registry.md
index ff8bfec..17f4247 100644
--- a/docs/memory/component-registry.md
+++ b/docs/memory/component-registry.md
@@ -51,7 +51,7 @@ duplicates) and MUST update it after completing one.
|-----------|--------|-------------|-------|
| ServiceSelector | done | ServiceOption × n + Typography + Button | Single-select service panel for arrangement flow. Heading + subheading + ServiceOption list (radiogroup) + optional continue Button. Manages selection state via selectedId/onSelect. maxDescriptionLines pass-through. |
| PricingTable | planned | PriceCard × n + Typography | Comparative pricing display |
-| ArrangementForm | review | StepIndicator + ServiceSelector + AddOnOption + Button + Typography | Multi-step arrangement wizard. Controlled by parent (currentStep/onNext/onBack). Each step renders arbitrary content with consistent nav buttons. canContinue per step. Back/Continue/Complete labels configurable. |
+| ArrangementForm | planned | StepIndicator + ServiceSelector + AddOnOption + Button + Typography | Multi-step arrangement wizard. Deferred — build remaining atoms/molecules first. |
| Navigation | done | AppBar + Link + IconButton + Button + Divider + Drawer | Responsive site header. Desktop: logo left, links right, optional CTA. Mobile: hamburger + drawer with nav items, CTA, help footer. Sticky, grey surface bg (surface.subtle). Real FA logo from brandassets/. Maps to Figma Main Nav (14:108) + Mobile Header (2391:41508). |
| Footer | done | Link × n + Typography + Divider + Container + Grid | Dark espresso (brand.950) site footer. Logo + tagline + contact (phone/email) + link group columns + legal bar. Semantic HTML (footer, nav, ul). Critique: 38/40 (Excellent). |
diff --git a/src/components/organisms/ArrangementForm/ArrangementForm.stories.tsx b/src/components/organisms/ArrangementForm/ArrangementForm.stories.tsx
deleted file mode 100644
index 62719a9..0000000
--- a/src/components/organisms/ArrangementForm/ArrangementForm.stories.tsx
+++ /dev/null
@@ -1,380 +0,0 @@
-import { useState } from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
-import Box from '@mui/material/Box';
-import { ArrangementForm } from './ArrangementForm';
-import { ServiceSelector } from '../ServiceSelector';
-import { AddOnOption } from '../../molecules/AddOnOption';
-import { Typography } from '../../atoms/Typography';
-import { Navigation } from '../Navigation';
-
-// ─── Shared data ─────────────────────────────────────────────────────────────
-
-const serviceTypes = [
- { id: 'burial', name: 'Traditional Burial', price: 4200, description: 'Full service with chapel ceremony, viewing, hearse, and graveside committal.' },
- { id: 'cremation', name: 'Cremation with Service', price: 2800, description: 'Chapel ceremony followed by cremation. Ashes returned in a standard urn.' },
- { id: 'direct-cremation', name: 'Direct Cremation', price: 1600, description: 'Simple cremation without a formal service. Ashes returned within 5 business days.' },
-];
-
-const coffinOptions = [
- { id: 'eco', name: 'Eco Willow', price: 850, description: 'Handwoven natural willow. Biodegradable and sustainable.' },
- { id: 'classic', name: 'Classic Maple', price: 1400, description: 'Solid maple with satin finish and brass handles.' },
- { id: 'premium', name: 'Premium Oak', price: 2200, description: 'Quarter-sawn oak with high-gloss lacquer and gold-plated handles.' },
-];
-
-const addOns = [
- { id: 'flowers', name: 'Floral Arrangements', price: 450, description: 'Seasonal flowers for the chapel and casket spray.' },
- { id: 'video', name: 'Memorial Video', price: 350, description: 'Professional video tribute with photos and music, played during the service.' },
- { id: 'catering', name: 'Wake Catering', price: 800, description: 'Light refreshments for up to 50 guests after the service.' },
- { id: 'transport', name: 'Family Limousine', price: 300, description: 'Luxury vehicle for immediate family to and from the service.' },
- { id: 'death-notice', name: 'Newspaper Death Notice', price: 180, description: 'Published in one major metropolitan newspaper of your choice.' },
-];
-
-const FALogoNav = () => (
-
-);
-
-// ─── Meta ────────────────────────────────────────────────────────────────────
-
-const meta: Meta = {
- title: 'Organisms/ArrangementForm',
- component: ArrangementForm,
- tags: ['autodocs'],
- parameters: {
- layout: 'centered',
- },
- decorators: [
- (Story) => (
-
-
-
- ),
- ],
-};
-
-export default meta;
-type Story = StoryObj;
-
-// --- Default (Static) --------------------------------------------------------
-
-/** Static view at step 1 — shows structure without interactivity */
-export const Default: Story = {
- args: {
- heading: 'Plan your arrangement',
- subheading: 'We\'ll guide you through each step. You can go back and change your selections at any time.',
- steps: [
- { label: 'Service', content: Service selection content },
- { label: 'Coffin', content: Coffin selection content },
- { label: 'Extras', content: Optional extras content },
- { label: 'Review', content: Review summary content },
- ],
- currentStep: 0,
- },
-};
-
-// --- Interactive Full Flow ---------------------------------------------------
-
-/** Complete 4-step arrangement flow with real components */
-export const InteractiveFlow: Story = {
- render: () => {
- const [step, setStep] = useState(0);
- const [serviceId, setServiceId] = useState();
- const [coffinId, setCoffinId] = useState();
- const [selectedAddOns, setSelectedAddOns] = useState>({});
-
- const toggleAddOn = (id: string, checked: boolean) => {
- setSelectedAddOns((prev) => ({ ...prev, [id]: checked }));
- };
-
- const getServiceName = () => serviceTypes.find((s) => s.id === serviceId)?.name ?? '—';
- const getServicePrice = () => serviceTypes.find((s) => s.id === serviceId)?.price ?? 0;
- const getCoffinName = () => coffinOptions.find((c) => c.id === coffinId)?.name ?? '—';
- const getCoffinPrice = () => coffinOptions.find((c) => c.id === coffinId)?.price ?? 0;
- const getAddOnTotal = () =>
- addOns.filter((a) => selectedAddOns[a.id]).reduce((sum, a) => sum + a.price, 0);
- const getTotal = () => getServicePrice() + getCoffinPrice() + getAddOnTotal();
-
- const steps = [
- {
- label: 'Service',
- canContinue: !!serviceId,
- content: (
-
- ),
- },
- {
- label: 'Coffin',
- canContinue: !!coffinId,
- content: (
-
- ),
- },
- {
- label: 'Extras',
- canContinue: true,
- content: (
-
-
- Optional extras
-
-
- Add any optional services. You can skip this step if none are needed.
-
-
- {addOns.map((addOn) => (
- toggleAddOn(addOn.id, checked)}
- maxDescriptionLines={1}
- />
- ))}
-
-
- ),
- },
- {
- label: 'Review',
- canContinue: true,
- content: (
-
-
- Review your arrangement
-
-
- {/* Service */}
-
-
- Service
-
-
- {getServiceName()}
-
- ${getServicePrice().toLocaleString('en-AU')}
-
-
-
-
- {/* Coffin */}
-
-
- Coffin
-
-
- {getCoffinName()}
-
- ${getCoffinPrice().toLocaleString('en-AU')}
-
-
-
-
- {/* Extras */}
- {addOns.filter((a) => selectedAddOns[a.id]).length > 0 && (
-
-
- Extras
-
- {addOns
- .filter((a) => selectedAddOns[a.id])
- .map((addOn) => (
-
- {addOn.name}
-
- ${addOn.price.toLocaleString('en-AU')}
-
-
- ))}
-
- )}
-
- {/* Total */}
-
- Estimated total
-
- ${getTotal().toLocaleString('en-AU')}
-
-
-
-
- This is an estimate only. Final pricing will be confirmed by your chosen funeral director.
-
-
- ),
- },
- ];
-
- return (
- setStep((s) => Math.min(s + 1, steps.length - 1))}
- onBack={() => setStep((s) => Math.max(s - 1, 0))}
- onComplete={() => alert(`Arrangement complete! Total: $${getTotal().toLocaleString('en-AU')}`)}
- />
- );
- },
-};
-
-// --- Mid-Flow ----------------------------------------------------------------
-
-/** Starts at step 2 with prior selections visible */
-export const MidFlow: Story = {
- args: {
- steps: [
- { label: 'Service', content: Completed },
- { label: 'Coffin', content: Completed },
- {
- label: 'Extras',
- content: (
-
-
- Optional extras
-
-
- Add any optional services you'd like.
-
-
- {addOns.slice(0, 3).map((addOn) => (
-
- ))}
-
-
- ),
- },
- { label: 'Review', content: Review step },
- ],
- currentStep: 2,
- },
-};
-
-// --- Two Steps ---------------------------------------------------------------
-
-/** Simplified 2-step flow for simpler arrangements */
-export const TwoSteps: Story = {
- render: () => {
- const [step, setStep] = useState(0);
- const [serviceId, setServiceId] = useState();
-
- return (
-
- ),
- },
- {
- label: 'Review',
- content: (
-
-
- Confirm your selection
-
-
- {serviceTypes.find((s) => s.id === serviceId)?.name ?? 'Nothing selected'}
-
-
- ),
- },
- ]}
- currentStep={step}
- onNext={() => setStep(1)}
- onBack={() => setStep(0)}
- onComplete={() => alert('Complete!')}
- completeLabel="Confirm arrangement"
- />
- );
- },
-};
-
-// --- In Page Context ---------------------------------------------------------
-
-/** Full page with Navigation wrapping the arrangement flow */
-export const InPageContext: Story = {
- decorators: [
- (Story) => (
-
-
-
- ),
- ],
- render: () => {
- const [step, setStep] = useState(0);
- const [serviceId, setServiceId] = useState();
-
- return (
-
- }
- items={[
- { label: 'FAQ', href: '/faq' },
- { label: 'Contact Us', href: '/contact' },
- ]}
- />
-
-
- ),
- },
- { label: 'Coffin', content: Coffin step... },
- { label: 'Extras', content: Extras step... },
- { label: 'Review', content: Review step... },
- ]}
- currentStep={step}
- onNext={() => setStep((s) => s + 1)}
- onBack={() => setStep((s) => s - 1)}
- onComplete={() => alert('Done!')}
- />
-
-
- );
- },
-};
diff --git a/src/components/organisms/ArrangementForm/ArrangementForm.tsx b/src/components/organisms/ArrangementForm/ArrangementForm.tsx
deleted file mode 100644
index 7969ef8..0000000
--- a/src/components/organisms/ArrangementForm/ArrangementForm.tsx
+++ /dev/null
@@ -1,174 +0,0 @@
-import React from 'react';
-import Box from '@mui/material/Box';
-import type { SxProps, Theme } from '@mui/material/styles';
-import { Typography } from '../../atoms/Typography';
-import { Button } from '../../atoms/Button';
-import { StepIndicator } from '../../molecules/StepIndicator';
-
-// ─── Types ───────────────────────────────────────────────────────────────────
-
-/** A single step in the arrangement flow */
-export interface ArrangementStep {
- /** Step label shown in the StepIndicator */
- label: string;
- /** Step content — rendered when this step is active */
- content: React.ReactNode;
- /** Whether the user can proceed past this step. Defaults to true. */
- canContinue?: boolean;
-}
-
-/** Props for the FA ArrangementForm organism */
-export interface ArrangementFormProps {
- /** The steps in the arrangement flow */
- steps: ArrangementStep[];
- /** Current step index (0-based). Controlled by parent. */
- currentStep: number;
- /** Called when the user advances to the next step */
- onNext?: () => void;
- /** Called when the user goes back to the previous step */
- onBack?: () => void;
- /** Called when the user completes the final step */
- onComplete?: () => void;
- /** Label for the next button — defaults to "Continue" */
- nextLabel?: string;
- /** Label for the back button — defaults to "Back" */
- backLabel?: string;
- /** Label for the final step's button — defaults to "Review arrangement" */
- completeLabel?: string;
- /** Optional heading above the step content */
- heading?: string;
- /** Optional subheading below the heading */
- subheading?: string;
- /** MUI sx prop for the root element */
- sx?: SxProps;
-}
-
-// ─── Component ───────────────────────────────────────────────────────────────
-
-/**
- * Multi-step arrangement form for the FA design system.
- *
- * The core planning flow — guides users through service selection,
- * coffin choice, venue, extras, and review. Each step renders
- * arbitrary content (ServiceSelector, AddOnOption lists, forms, etc.)
- * with consistent navigation and progress indication.
- *
- * Composes StepIndicator + Typography + Button + step content.
- *
- * State is controlled by the parent — the form doesn't own step
- * state or selection state. This keeps it composable and testable.
- *
- * Usage:
- * ```tsx
- * , canContinue: !!selected },
- * { label: 'Coffin', content: },
- * { label: 'Extras', content: },
- * { label: 'Review', content: },
- * ]}
- * currentStep={step}
- * onNext={() => setStep(s => s + 1)}
- * onBack={() => setStep(s => s - 1)}
- * onComplete={() => submit()}
- * />
- * ```
- */
-export const ArrangementForm = React.forwardRef(
- (
- {
- steps,
- currentStep,
- onNext,
- onBack,
- onComplete,
- nextLabel = 'Continue',
- backLabel = 'Back',
- completeLabel = 'Review arrangement',
- heading,
- subheading,
- sx,
- },
- ref,
- ) => {
- const isFirstStep = currentStep === 0;
- const isLastStep = currentStep === steps.length - 1;
- const activeStep = steps[currentStep];
- const canContinue = activeStep?.canContinue ?? true;
-
- const stepLabels = steps.map((s) => ({ label: s.label }));
-
- return (
-
- {/* Progress indicator */}
-
-
- {/* Optional heading */}
- {heading && (
-
-
- {heading}
-
- {subheading && (
-
- {subheading}
-
- )}
-
- )}
-
- {/* Step content */}
-
- {activeStep?.content}
-
-
- {/* Navigation buttons */}
-
- {!isFirstStep ? (
-
- ) : (
-
- )}
-
-
-
-
- );
- },
-);
-
-ArrangementForm.displayName = 'ArrangementForm';
-export default ArrangementForm;
diff --git a/src/components/organisms/ArrangementForm/index.ts b/src/components/organisms/ArrangementForm/index.ts
deleted file mode 100644
index 2390bfe..0000000
--- a/src/components/organisms/ArrangementForm/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ArrangementForm, type ArrangementFormProps, type ArrangementStep } from './ArrangementForm';
diff --git a/src/components/organisms/Footer/Footer.tsx b/src/components/organisms/Footer/Footer.tsx
index 7d1f397..dc171cd 100644
--- a/src/components/organisms/Footer/Footer.tsx
+++ b/src/components/organisms/Footer/Footer.tsx
@@ -80,6 +80,19 @@ export const Footer = React.forwardRef(
const year = new Date().getFullYear();
const copyrightText = copyright || `\u00A9 ${year} Funeral Arranger. All rights reserved.`;
+ const overlineSx = {
+ color: 'var(--fa-color-brand-400)',
+ textTransform: 'uppercase' as const,
+ letterSpacing: '0.08em',
+ display: 'block',
+ mb: 0.5,
+ };
+
+ const contactLinkSx = {
+ color: 'var(--fa-color-white)',
+ '&:hover': { color: 'var(--fa-color-brand-300)' },
+ };
+
return (
(
{phone && (
-
+
Call us
{phone}
@@ -141,25 +140,12 @@ export const Footer = React.forwardRef(
)}
{email && (
-
+
Email
{email}