Canonical demo data: Matt Belcher · 456 Sunset Blvd, Los Angeles CA 90028 · Exchange #1087 · $850,000 · SSN masked to ••••6789 · Sale date: Jun 1 2026 · 45-day deadline: Jul 16 2026 · 180-day deadline: Nov 28 2026
Real Implementation References (build agents: reuse these, don't reinvent)
These mockup classes/panels above are the visual doctrine. Below is what actually ships them in
packages/web-app/src
today. Full mapping + honest inconsistency notes: docs/mockups/STATES_GALLERY.md.
• Empty — no shared EmptyState primitive; each surface defines its own (e.g. DashboardEmptyState in pages/redesign/DashboardPage.tsx, EmptyState in pages/admin/platform/ReportingSection.tsx). Gallery's ID Hub / docs / escrow panels are the composed reference for new surfaces.
• Loading (skeleton) — DashboardLoadingSkeleton (pages/redesign/DashboardPage.tsx) and Form8824PrefillSkeleton (pages/FormsPage.tsx) are the canonical hand-rolled skeleton pattern (no shared Skeleton primitive exists).
• Loading (spinner) — components/ui/Spinner.tsx / components/ui/LoadingSpinner.tsx, for inline/button loading only — never fullscreen, matching the doctrine above.
• Toast — react-hot-toast, mounted once in main.tsx (`<Toaster/>`), called via toast.success() / toast.error() at call sites (e.g. components/wizard/CPASharePanel.tsx, ConstructionHub.tsx).
• Blocked / gated submit — components/wizard/HubTemplate.tsx disables the step submit button on !activeStep.fieldsComplete; shared across all 7 hub components.
Empty State — ID Hub: No Properties
Exchanger has not yet identified any replacement properties. Primary CTA above secondary empty-state hint.
Identification Hub
45-day window · Exchange #1087 · Matt Belcher
Auto-saved
forty-five-day-id-watcher · not yet armed
31 days remaining· Jul 16, 2026 at 11:59 PM§1031 · Treas. Reg. §1.1031(k)-1(b)
Identify your replacement properties
Neela · AI Exchange Assistant
You have 31 days to identify up to 3 replacement properties under the 3-property rule. I can search listings, evaluate candidates, and draft your Identification Notice once you're ready.
No properties identified yet
Your 45-day identification window is open. Add your first property above to begin.
Pattern: .cta-card (Add Property) is always visible ABOVE .empty-state. The empty-state is the secondary hint, never the primary affordance. Footer CTA is disabled until at least one property is identified.
Empty State — Documents: No Uploads
Document checklist before any files are uploaded. Upload CTA first, then the empty accordion below.
Sales Hub — Docs Tab (empty).cta-card.sales
Upload your closing documents
I'll extract sale price, closing date, and parcel number automatically. You'll review before anything is saved.
Neela guides and drafts. She never moves, holds, or releases your funds — that takes multi-party approval.
Awaiting wire from closing
Your 45-day clock started on the day your relinquished property closed, and your QI officer separately confirms receipt of the wired proceeds. The escrow-funds-received workflow that would detect the wire on its own is not built yet, so confirmation is recorded by a person.
No funds received yet
$850,000 expected · Your QI officer records receipt — escrow-funds-received · not yet armed
The constructive-receipt guardrail .section-card--warning with ShieldCheck is non-dismissible and always rendered before any fund-movement action.
Empty State — Admin: No Exchanges
QI Ops or Platform Ops when no exchanges exist for a filter / org. Indigo admin chrome, not hub color.
No exchanges match this filter · start a new one or adjust filters
No exchanges found
Try removing filters, or verify that dashboard-kpi-update has synced recently
Loading State — Hub Skeleton
Shown while hub data loads from Supabase. Header/tabs/footer preserve layout; content area replaces with skeletons + ping autosave-dot.
Loading…
Header, tabs, and footer preserve actual dimensions during skeleton — never collapse or hide them. The frame must not jump when data loads.
Loading State — Consumer Dashboard
KPI tiles, countdown rings, and live workflow feed are all skeleton-replaced. Vectr badge names are shown as ghost placeholders.
Zone A — Assurance Band
Zone B — Neela Briefing
Zone C — Live Automation Feed
KPI data sources are dashboard-kpi-update (hourly + on state change). Skeleton rows are sized to match actual content height so the layout does not reflow on load.
Loading State — Neela Thinking
Neela is processing a tool call or generating a response. Animated shimmer inside the tip card; action buttons disabled.
Neela thinking uses the dot-bounce animation for chat context and skeleton shimmer for tip context. Never show a fullscreen spinner — the hub frame stays visible at all times.
Error — Vectr Platform Outage
Vectr workflows are unreachable. Critical banner in hub header; form data still viewable but submission and automation are blocked.
Your form data is saved locally and will sync when connectivity restores. Your deadline dates are stored on the exchange record and are unaffected by this outage. The forty-five-day-id-watcher and one-eighty-day-deadline-guard workflows are not built yet, so no reminder resumes when you reconnect — Aug 14 and Dec 27 are still yours to watch.
Affected Workflows
45-day deadline watcherforty-five-day-id-watcher · not yet armed
Autosave to Supabasewizard-state-autosave · paused
E-sign orchestrationesign-orchestration · paused
View-only access to all exchange data and documents remains available. No data has been lost.
Vectr outage is always a full-width critical banner in the hub header zone, not a toast. The constructive-receipt guardrail: no fund-movement is attempted during outage — workflows resume from durable state when connectivity restores.
Error — Webhook Signature Mismatch
An inbound webhook (DocuSign, Plaid, Persona, or Vectr) failed HMAC signature verification. QI admin alert; affected step shows warning.
Received webhook for envelope env_7f3a92c1 but HMAC-SHA256 did not match. Event discarded. esign-orchestration will retry in 30 seconds.
E-sign status unconfirmed· Webhook retry pending
Plaid / Bank Webhook — Unverified.error-banner.warning + .status-badge.missing
Plaid Webhook — Signature Not Verified
Fund receipt for exchange #1087 could not be verified against the bank record. Escrow status stays unconfirmed until a QI officer reconciles it by hand — escrow-funds-received is not built yet, so nothing retries this on its own.
Funds unconfirmed
$850,000 · pending verification
Webhook mismatch uses .error-banner.warning (amber), not critical. The affected workflow badge changes color to amber. No user action unblocks the step — the retry is automatic via error-alerting-retry.
Error — Save Failed
Autosave to Supabase failed. Inline banner replaces the autosave-pill; data is queued locally. All three variants: transient, persistent, and conflict.
3 autosave attempts failed. Your changes are held in memory and will be retried when connectivity is restored. Do not close this tab. wizard-state-autosave will resume automatically.
This exchange was updated in another session 2 minutes ago. Reload to get the latest version, or overwrite with your current changes.
Save-failed banners replace the .autosave-pill in the header row — they do not stack below content. Critical (3 retries exhausted) and conflict variants require explicit user resolution. Transient (retrying) auto-dismisses on success.
Error — Blocked Submit
Hub cannot advance because of a missing prerequisite, failed validation, or compliance block. Footer CTA disabled; risk pills and status badges explain why.
ID Hub — Submit Blocked (no properties + KYC incomplete).risk-pill.critical + .status-badge.missing + disabled CTA
Hub submission is blocked
Resolve all items below before continuing. compliance-risk-checks flagged 2 issues.
No replacement properties identified
Required
KYC verification incomplete — pending Persona review
Blocked
2 blocking issues
31 days remaining
compliance-risk-checks · flagged
Prerequisite Locked — Hub not yet unlocked.section-card (prerequisite banner)
Purchase Hub is locked
Complete the Identification Hub and confirm funds are in escrow before purchasing a replacement property. Your 180-day window opened on the day the relinquished property transferred, and today that closing is entered by a QI officer. The escrow-funds-received workflow that would detect the wire on its own is not built yet, so confirmation is recorded by a person.
Blocked submit: the Continue CTA is always visible but disabled with opacity:0.35 — never hidden. The BlockedSubmitPanel card explains every issue with an actionable item. Risk pills summarize the count at a glance.
Neela Offline — Degrade to Text
When the Neela AI endpoint is unreachable, voice/action chips and the avatar gradient go grey. Static guidance text replaces the AI response. Layout does not collapse.
Neela — Online (reference).neela-tip (normal)
Ready to help
Neela · AI Exchange Assistant · online
You have 31 days to identify up to 3 replacement properties. Your $850,000 is safe in segregated escrow.
Neela — Offline (degrade to text).neela-offline
Neela
offline
AI assistant is temporarily unavailable. Below is guidance based on your exchange status:
Next step: Identify up to 3 replacement properties before Jul 16, 2026 (your 45-day deadline). Under the 3-property rule (§1031), you may name up to 3 properties regardless of value. Your $850,000 is held in segregated QI escrow.
AI features will restore automatically. Hub forms are fully operational.
Neela Chat — Offline (text-only mode).neela-offline-badge + text fallback
What are the IRS identification rules?
offline · text only
Under §1031, you may identify using: 3-property rule (any 3 properties, any value), 200% rule (any number, FMV ≤ 200% of relinquished), or 95% rule (any number if 95% of FMV is actually acquired). Deadline: 45 calendar days from closing, midnight local time. Signed written notice delivered to QI is required — oral identification does not count.
Neela offline: gradient avatar becomes #334155 grey, action chip buttons are removed, static compliance-correct text replaces the AI response. The layout dimensions are preserved exactly — no reflow or collapsed whitespace. Voice features are hidden (not disabled) offline.
Neela State Variants
All tip/avatar states: normal, safe chip, warning chip, needs-approval guardrail, success, and offline. The frozen primitive — never recolored or restyled.
Normal tip — informational.neela-tip
Neela · AI Exchange Assistant
Identification Hub · Exchange #1087
You have 31 days to identify up to 3 replacement properties. I can search listings by price range, location, or asset class.
I've drafted the wire release instructions for $850,000 to 789 Ocean Ave, Santa Monica CA. Review the details below and submit the request; two authorized officers, proposer distinct from approver, authorize the transfer before any funds move.
Neela guides and drafts. She never moves, holds, or releases your funds — that takes multi-party approval.escrow-wire-release · needs-approval
3 properties identified · Identification Notice signed · Delivered to QI Priya Raman
On track
identification-notice-generate · done
Neela avatar = linear-gradient(135deg,#2563eb,#6366f1) always. The guardrail line "Neela guides and drafts. She never moves, holds, or releases your funds — that takes multi-party approval." is rendered for every money-movement workflow row and is non-dismissible.
Build contract — state coverage
1 · Every async surface ships four states, not one. Loading, empty, error and offline
are specified here as first-class designs. A screen that only has a happy path is not finished, and a
spinner is not a loading state — skeletons preserve layout so nothing jumps when data lands. 2 · An empty state teaches. It names what would appear here, what triggers it, and the
one action that moves the file forward. It never scolds and never invents urgency. 3 · An error state names the failure and the recovery. What failed, whether the data is
safe, what is being retried and when, and what the reader can do now. Transient failures auto-clear on
success; exhausted retries and write conflicts require explicit human resolution. 4 · Severity is never colour alone. Each banner carries an icon, a title and a written
verdict alongside its wash, so the pattern survives monochrome and colour-vision deficiency. There is no
side-stripe: the state lives in the whole container, not a decorative edge. 5 · A deadline state never lies. An overdue statutory clock renders in the danger role
with the overrun stated — it can never resolve to a satisfied or green state. 45/180-day dates are not
editable from a state; only an approved four-eyes override with a recorded legal basis moves one. 6 · Neela degrades honestly. When the assistant is unreachable the surface says so and
falls back to the deterministic path, rather than presenting a stale or invented answer. 7 · Tokens only, both themes. A state gallery that can only be viewed in one theme is
half a gallery. Every specimen reads from tokens.css; filled hub buttons take their
matching --*-on foreground rather than a hardcoded white, which fails AA on every
dark-theme hub fill. All data synthetic.