# Component Contracts

Every component below is implemented once for all locales, directions, and themes. Props are semantic; components do not fetch translations internally unless the architecture establishes a single typed content boundary.

## SiteHeader

**Purpose:** Primary navigation, brand, locale/theme controls, login, demo CTA

**States:** `default,scrolled`

**Typed data:** `HeaderModel`

**Copy namespace:** `header.*`

**Responsive:** Desktop at >=1120; drawer trigger below

**RTL:** Nav order reverses naturally; logo unchanged; directional icons selective

**Accessibility:** Sticky; 44px targets; skip-link precedes it

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## MobileDrawer

**Purpose:** Compact/medium navigation overlay

**States:** `closed,open`

**Typed data:** `DrawerModel`

**Copy namespace:** `header.*`

**Responsive:** Inline-start fixed drawer <=384px or 88vw

**RTL:** Opens right in RTL

**Accessibility:** Trap focus; inert background; Escape; focus return

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## LocaleSelector

**Purpose:** Switch locale by stable route ID

**States:** `closed,open,disabled`

**Typed data:** `LocaleSelectorProps`

**Copy namespace:** `language names`

**Responsive:** Native select baseline

**RTL:** Order EN/FR/AR; control follows document direction

**Accessibility:** Labelled; current locale selected; preserves route/hash

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## ThemeSelector

**Purpose:** Set Light/Dark/System preference

**States:** `light,dark,system`

**Typed data:** `ThemeSelectorProps`

**Copy namespace:** `header.light/dark/system`

**Responsive:** Native select or accessible segmented control

**RTL:** No mirroring needed

**Accessibility:** Cookie+storage; immediate; live system updates

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## HeroSection

**Purpose:** Communicate category, promise, primary and secondary actions

**States:** `default`

**Typed data:** `HeroModel`

**Copy namespace:** `hero.*`

**Responsive:** 1 column <1120; 7/5 split wide

**RTL:** Text aligns start; preview uses actual RTL rendering

**Accessibility:** One h1; CTA order follows document direction

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## ProductPreview

**Purpose:** Illustrative/evidence-governed product visual

**States:** `illustrative,approved-capture`

**Typed data:** `ProductPreviewModel`

**Copy namespace:** `preview.*`

**Responsive:** Simplify data table on compact

**RTL:** Do not mirror screenshots; coded preview renders RTL

**Accessibility:** Accessible caption; no false product claim

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## LifecycleProof

**Purpose:** Show operational coverage without customer logos

**States:** `default`

**Typed data:** `LifecycleItem[]`

**Copy namespace:** `trust.*`

**Responsive:** 1/2/4 columns by available width

**RTL:** Sequence follows reading direction

**Accessibility:** List semantics; icons decorative

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## ComparisonSection

**Purpose:** Fragmented versus connected workflow

**States:** `default`

**Typed data:** `ComparisonModel`

**Copy namespace:** `comparison.*`

**Responsive:** Stack compact; two columns medium+

**RTL:** Order follows locale reading direction

**Accessibility:** Headings identify both columns; do not rely on color

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## WorkflowSteps

**Purpose:** Four-step rental flow and tour source

**States:** `default`

**Typed data:** `WorkflowStep[]`

**Copy namespace:** `workflow.*`

**Responsive:** 1 column compact; 4 columns >=768

**RTL:** Step order follows reading direction

**Accessibility:** Ordered list; numerals isolated if needed

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## RoleCards

**Purpose:** Explain value by operating role

**States:** `default`

**Typed data:** `RoleCard[]`

**Copy namespace:** `roles.*`

**Responsive:** 1/2/4 columns content-driven

**RTL:** Same tree; start alignment

**Accessibility:** Heading hierarchy and readable card order

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## ModuleGrid

**Purpose:** Describe approved product modules

**States:** `default`

**Typed data:** `ModuleCard[]`

**Copy namespace:** `modules.*`

**Responsive:** 1/2/3 columns

**RTL:** Same tree; directional icons selective

**Accessibility:** No capability beyond approved copy

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## MeasurementPlan

**Purpose:** Show KPI definitions without invented outcomes

**States:** `default`

**Typed data:** `MetricDefinition[]`

**Copy namespace:** `results.*`

**Responsive:** Cards plus methodology block

**RTL:** Same tree

**Accessibility:** No unapproved numbers; ordered methodology

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## IntegrationCategories

**Purpose:** Neutral category list

**States:** `default`

**Typed data:** `IntegrationCategory[]`

**Copy namespace:** `integrations.*`

**Responsive:** Cloud/list adapts without clipping

**RTL:** Same tree

**Accessibility:** No partner logos until verified

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## SecurityChecklist

**Purpose:** Evidence-request checklist

**States:** `default`

**Typed data:** `SecurityCheck[]`

**Copy namespace:** `security.*`

**Responsive:** 1/2 columns

**RTL:** Same tree

**Accessibility:** No badges/certifications without approval

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## PricingPreview

**Purpose:** Explain pricing factors and demo route

**States:** `quote-only,approved-pricing`

**Typed data:** `PricingModel`

**Copy namespace:** `pricing.*`

**Responsive:** Stack compact; 2 columns >=768

**RTL:** Same tree

**Accessibility:** Never imply public price when absent

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## FAQAccordion

**Purpose:** Localized questions and answers

**States:** `closed,open`

**Typed data:** `FaqItem[]`

**Copy namespace:** `faq.*`

**Responsive:** Single column

**RTL:** Chevron mirrors only if it conveys expansion direction

**Accessibility:** Native details baseline; keyboard and SR tested

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## FinalCTA

**Purpose:** Final conversion block and approved secondary contact

**States:** `default`

**Typed data:** `FinalCtaModel`

**Copy namespace:** `finalCta.*`

**Responsive:** Stack compact; 2 columns >=768

**RTL:** CTA order follows document direction

**Accessibility:** Secondary link suppressed until real destination approved

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## SiteFooter

**Purpose:** Localized navigation, legal, evidence status internal only

**States:** `default`

**Typed data:** `FooterModel`

**Copy namespace:** `footer.*`

**Responsive:** Stack then grouped columns

**RTL:** Same tree

**Accessibility:** No public internal proof-status label

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## DemoDialog

**Purpose:** Qualification form and submission states

**States:** `idle,invalid,submitting,success,recoverable-error,terminal-error`

**Typed data:** `DemoFormProps`

**Copy namespace:** `form.*`

**Responsive:** Modal max width; full-screen-safe compact

**RTL:** Field order follows reading direction; emails isolated

**Accessibility:** Focus trap, summary, inline errors, return focus

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.

## ProductTourDialog

**Purpose:** Four-step guided overview

**States:** `step-1,step-2,step-3,step-4,complete`

**Typed data:** `TourProps`

**Copy namespace:** `tour.*`

**Responsive:** Modal max width; compact-safe

**RTL:** Back/next positions follow reading direction but meaning stays explicit

**Accessibility:** Progress announced; focus moves to step heading

**Content rule:** Block size is content-driven. Unsupported evidence suppresses the component or uses the explicitly approved neutral variant.
