Lifts HelpBar out of WizardLayout's internal scope into
src/components/molecules/HelpBar/ so both WizardLayout and pages that
bypass WizardLayout's chrome (currently: ProvidersStep's mobile
map-first branch) render an identical sticky-footer.
Before: WizardLayout had an internal HelpBar with the right styling
(sticky, responsive px, phone format helper); ProvidersStep's
mobile-map branch hand-rewrote the footer inline and had drifted —
missing position: sticky, missing the md:4 responsive px, hard-coded
phone number bypassing the prop default. This consolidates both to
one source of truth.
Props: `phone?` (defaults to FA's support number, spaces preserved
in label, stripped in tel href) + `sx?` for caller chrome overrides.
Two Storybook stories (Default, CustomNumber).
Verified: footer text / height / sticky position identical between
mobile-list (WizardLayout) and mobile-map (direct HelpBar).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lifts the committed-chip location search pattern out of ProvidersStep
(two identical inline call sites, ~60 lines each) into a reusable
molecule. Behaviour unchanged: draft-typing → commit on Enter or the
primary-filled search button → chip render → tap X to clear.
The molecule owns the non-obvious correctness CSS (endAdornment
absolute-anchoring + right-side padding lane) internally so future
callers don't have to rediscover it. Chrome (bgcolor, shadow, border,
radius) stays caller-controlled via the `sx` prop — selector keys for
internal vs caller rules are kept distinct (.MuiAutocomplete-inputRoot
vs .MuiOutlinedInput-root) to avoid sx-merge collisions.
API: value (committed, chip-rendered) + onChange (fires on commit OR
chip-delete) + optional onCommit (fires only on explicit commit, for
side effects beyond state).
ProvidersStep trims ~160 lines net, drops searchDraft/commitSearch/the
SearchIcon/LocationOnOutlinedIcon/IconButton imports that only existed
to power the two inline instances.
Four Storybook stories: Empty, WithCommittedValue, Unstyled,
WithOnCommit — enough to iterate the molecule without a live page.
Verified: delta=0px on the search button position (empty→draft→chip)
at both mobile and desktop widths — matches pre-extraction behaviour.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New molecule MapProviderDrawer lifts the mobile-map bottom drawer out
of ProvidersStep (~120 lines): Paper + close-X header + single-pin
ProviderCard content / cluster-list content + slide-up animation.
Props: `active: ProviderMapActiveState | null`, `onClose`,
`onSelectProvider`, `onDrillIntoProvider`. Three Storybook states
(SingleProvider, Cluster, ClusterPair, Closed) so the drawer can be
iterated without a live map. ProvidersStep now consumes it as a
single line wired to mapRef.clearActive + mapRef.drillIntoProvider.
- Shared visual tokens for the control cluster (Search, Filters, Sort by,
List/Map toggle) factored into a CONTROL_CHROME constant and three
typed sx objects (controlButtonSx, controlToggleSx, controlInputSx,
filterTriggerSx) so all four controls share the same outline, radius,
fill, and shadow across mobile list, mobile map, and desktop. Desktop
map-panel floating toggle also re-threaded through controlToggleSx.
- Mobile list control order now matches mobile map: Sort by is grouped
left next to Filters (not pushed right with a ml:auto wrapper), and
the List/Map toggle is right-pinned via ml:auto on xs. Desktop keeps
Sort pushed right (no toggle rendered on desktop in this slot).
- Fix: the magnifying-glass commit button was drifting 19–30px left as
the input filled with chips / draft text. Root cause: overriding
`InputProps.endAdornment` on Autocomplete bypasses MUI's
`.MuiAutocomplete-endAdornment` absolute positioning, leaving our
`.MuiInputAdornment-positionEnd` as `position: static` in flex flow.
controlInputSx now re-absolutely-anchors the end adornment at the
right edge and reserves `pr: 5` so input content can't slide under it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Controls
- Mobile list view's Filters/Sort/view-toggle now match the mobile map
view's floating-chip treatment: white fill, neutral-300 border,
shadow-sm. On mobile the sort label switches from "Sort: <value>" to
a compact "Sort by"; desktop keeps its verbose label.
- List/Map toggle font bumped to 14px / 600 (button-small token), so
it reads on the same line as Filters + Sort by both on mobile and
on the desktop floating pill over the map panel.
PackagesStep drill-in
- Added a local hasDrilledIn flag so the mobile layout only swaps to
the detail view after an explicit user tap on a package. Previously
any pre-selection (the demo route seeds selectedPackageId to the
first matching package for desktop auto-display) also forced mobile
into the detail view, so users arriving from the map drawer saw a
single package instead of the list. Back/forward from the detail
resets the flag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MapPin (both tiers)
- Verified providers now get an inline verified tick on the left of
the name, matching the tick colour to the name so it reads as part
of the label. Inline SVG (not @mui/icons-material) because MapPin
is mounted via createRoot outside the ThemeProvider.
- Max label width bumped 180 → 210px to accommodate the icon without
aggressively truncating long names.
Mobile cluster drawer rows
- Verified icon aligns with the name's top line (flex-start + 1.25em
icon slot) — matches the desktop ClusterPopup layout.
- New right-aligned "From $X" price column, copper for verified.
Controls
- Mobile List/Map toggle: text labels (List, Map) instead of icons.
- Desktop List/Map toggle: resized to 32px height matching Filters +
Sort buttons; bigger type, more padding.
- Search input corner radius now matches the button radius (8px)
instead of the input radius (4px) so it reads as part of the chip
set rather than a separate control.
Filter dialog (desktop + mobile)
- Remove the Location field — the sticky search bar is primary.
- Funeral-type chips bump small → medium.
- Reset filters button always renders; disabled when no filters are
active (was previously hidden), so the affordance is discoverable.
- Provider-feature switches (Verified only, Online arrangements)
align to the first text line so wrapped labels don't sink the
switch visually below the second line.
Mobile drawer close
- drawerOpen now excludes the `exiting` phase, so tapping the X slides
the drawer down immediately instead of lingering with a stale
opacity fade. Visibility flips to hidden only after the slide ends.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Search, Filters, Sort by, and the List/Map toggle now share a
neutral-300 1px border and a shadow-sm drop, so the strip reads as a
coherent set of floating chips over the map (not a mix of different
button chromes)
- Drawer card now runs edge-to-edge inside the drawer with its own
border + shadow stripped; the drawer Paper provides the top radius
and the bottom is explicitly squared (no stray MUI default radius
leaking through)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Mobile-map search input gets an explicit white fill so it reads
cleanly against map tiles (desktop unchanged)
- Sort trigger on mobile-map is now a compact "Sort by" outlined
Button instead of a lone icon — clearer affordance than the swap
glyph, still tight on horizontal space
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the Paper container around the mobile-map floating controls —
each control (Filters, Sort, view toggle) now carries its own white
fill and reads over any map tile without a shared box
- Sort button becomes icon-only on mobile-map (the current sort is
still communicated via the aria-label and the menu) — saves the
row's horizontal budget
- Align all three controls to 32px height so Filters, Sort, and the
List/Map toggle sit on a common baseline
- Move the drawer close X out of the image overlay area into a
dedicated 40px drawer header bar; cluster header text ("N providers
in this area") now lives in the same strip. No more overlap with the
Verified badge on the card image.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On xs + viewMode=map, render a map-first layout: full-bleed map,
floating card-shaped control strip at the top (search + Filters +
Sort + compact List/Map toggle), and a bottom drawer that slides up
when a pin or cluster is tapped. The desktop list-map layout is
unchanged.
On xs + viewMode=list, the List/Map toggle now appears in the sticky
control bar (icon-only) so users can reach the map from the list view.
On desktop the toggle stays on the map panel as before.
Drawer content:
- Single pin → the existing ProviderCard molecule, entire card
clickable (navigates to packages)
- Cluster → a list of image-free rows (verified icon slot + name +
location + rating), tap a row to pan+zoom into the provider
- Close X on the drawer clears the active state
To support externalising popups, ProviderMap gains two opt-in props
(`externalisePopups`, `onActiveChange`) and an imperative handle
(`clearActive`, `drillIntoProvider`). Desktop behaviour unchanged
when these aren't used. The forwardRef now exposes the handle rather
than the DOM element; no existing callsite passed a DOM ref.
The filter-dialog children are now defined once as a shared JSX
fragment used by both desktop and mobile FilterPanel instances.
Header + subhead are suppressed on the mobile map view (per concept
reference); they remain on desktop and mobile list for orientation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Suppress Autocomplete's own popup/clear indicators (forcePopupIcon,
clearIcon) so the search IconButton stays anchored in the same spot
across empty, draft, and chip states
- Search button is a primary-filled circle at default strength in every
state (no disabled dimming) — a clear affordance, handler already
guards for empty drafts
- Drop the brand-gold focus ring on the search bar; keep the default
neutral border on focus
- Drop the copper 2px focus outline on Filters and Sort (outline: none
under :focus-visible)
- Committed location chip now uses the default neutral tonal fill
instead of the promoted brand colour
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sticky search now uses Autocomplete (multiple+freeSolo capped to 1)
instead of a plain TextField:
- Pin icon tightened to the left edge and to the placeholder
- Committed location renders inside the input as an FA Chip with an
X delete (clears the committed filter)
- Primary-coloured magnifying-glass IconButton on the right commits
the draft; disabled while the draft is empty
- Typing no longer filters live — Enter or the search button promotes
the draft to a chip, matching the chip mental model
The FilterPanel dialog's Location autocomplete already read from the
same searchQuery state, so it continues to display the committed chip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Sort button now reads "Sort: <value>" so it's distinguishable from
a filter; aria-label spells out the current sort. Price sort labels
dropped their internal colons (avoids double-colon rendering).
- Results count bolds the number in primary text so it registers as
the subject rather than incidental metadata.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces a full Google-Maps-backed provider map for the arrangement
wizard's ProvidersStep. Clicking a pin morphs it into a MapPopup at
the same coord; pins within 70px of each other collapse into a cluster
(ceiling at zoom 13) that opens a ClusterPopup list on click. Row
clicks pan + zoom the map to the provider and open their MapPopup.
Map-background click routes through an exit transition that fades the
popup out before reappearing the pin, via a matching fade-in keyframe
on the atom markers.
Key additions:
- @vis.gl/react-google-maps + @googlemaps/markerclusterer deps
- ClusterMarker atom (count badge; verified / unverified palettes)
- ClusterPopup molecule (image-free rows; verified icon aligned to
name; right-aligned "From $X" column; verified-first sort)
- ProviderMap organism (APIProvider + Map + imperative AdvancedMarker
layer via createRoot for clusterer compatibility)
Component changes:
- MapPin: promoted verified palette (brand-700); name now required;
name-only and price-only variants dropped; active prop removed in
favour of organism-level state; SVG nub with fill+stroke replaces
the CSS border-triangle trick so the outline is continuous
- MapPopup: `exiting` prop drives close animation; click events stop
propagation so the map's onClick can't clear state mid-interaction
- ProviderData type gains optional `coords`; demo fixtures populated
with real NSW/QLD lat/lng for all 7 providers
- ProvidersStep demo route wires ProviderMap into the mapPanel slot
Memory:
- docs/memory/component-registry updated (ClusterMarker, ClusterPopup,
ProviderMap added; MapPin + MapPopup refined; MapCard retired)
- docs/memory/session-log captures arc across 2026-04-21/22 and flags
next-session work: ProvidersStep polish, mobile layout for list-map
WizardLayout, and demo deploy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes images 404'ing under /arrangement/ — Vite's publicDir copies assets
to the build root, but the base prefix is only applied to bundled assets
(JS/CSS), not to runtime URL strings. assetUrl() helper resolves paths
against import.meta.env.BASE_URL so '/images/foo.png' becomes
'/arrangement/images/foo.png' in production while staying '/images/foo.png'
in dev.
- src/demo/shared/assets.ts — assetUrl() helper
- providers.ts + DemoNav.tsx — wrap all public asset paths
- nginx/parsons-demos.conf — swag site-conf for parsons.tensordesign.com.au
(asset cache regex above SPA fallback regex per nginx first-match rule)
- docs/reference/client-demo-deploy.md — server runbook (DNS, swag
SUBDOMAINS, mount, htpasswd, deploy loop)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a self-contained demo build target for the Providers → Packages →
Comparison flow, deployable as a static SPA at /arrangement/.
- vite.demo.config.ts: per-slice build via --mode, base path flips for
dev vs prod, output to dist-demo/<slice>/
- src/demo/: shared fixtures (7 providers across verified/tier3/tier2
with real venue photography from brandassets) + Zustand basket store
with ?compare= URL persistence
- Verified-provider packages now share the nine canonical Essentials
line items per FA convention; only Optionals/Extras vary
- App-level CompareBar surfaces "Already added" / "Maximum 3" feedback
via transient store error
- ProviderCard logo objectFit cover→contain so wide logos don't crop
- npm scripts demo:dev / demo:build, deps zustand + react-router-dom
Consolidate the three tier pages (PackagesStep, UnverifiedPackageT2,
UnverifiedPackageT3) into a single tier-aware PackagesStep with
providerTier: 'verified' | 'tier3' | 'tier2'. Copy, CTA label, price
disclaimer, and itemised-unavailable state all derive from tier via
an internal TIER_COPY map.
Extract NearbyPackageCard as a molecule (was duplicated inline in T2
and T3). Inherits Card atom's default elevated variant so shadow
matches the primary ServiceOption cards in the same column.
Add showAllFromProvider variant for the "See N more packages from
this provider" flow — flat list, no grouping, no secondary list,
preference filter dropped.
Polish pass on PackagesStep + PackageDetail:
- PackageDetail header band warm → white; added card drop-shadow.
- onCompare prop wire-through (button was built in but never exposed).
- Price disclaimer info-box: padding/gap/line-height tuned, icon
alignment fixed (mt: '3px' matches codebase convention for 16px
icons paired with body2 text).
- Left-column vertical rhythm: 48px gaps between provider card /
subheading / list; 128px gap (Divider my: 8) between primary and
secondary sections to separate groupings.
- Mobile drill-in navigation via useMediaQuery + display toggles.
onSelectPackage widened to accept string | null; Back button
swaps to "Back to packages" when a package is selected on mobile.
Scrolls to top on drill-in.
- "See all" link copy: "See N more packages from this provider →"
(overflow count, no provider name — sidesteps long-name wrapping).
- Verified provider image: placeholder URL → real local asset
(hparsonsvenue.jpg, resized 2048×1366/591KB → 640×427/52KB).
Delete legacy PackageSelectPage story in PackageDetail.stories.tsx
(predated the real page components).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ComparisonTabCard: width 210 → 235; recommended badge switched to
filled brand + StarRoundedIcon matching the desktop
ComparisonColumnCard treatment; removed glow + active glow shadow in
favour of the standard shadow-sm; border colour brand-500 → brand-600;
pt 2.4 → 3.5.
- ComparisonPackageCard: verified badge replaced with inline
VerifiedOutlinedIcon to the left of the provider name (matches
desktop pattern); warm tint confined to the header (Card body now
explicitly white); 2px brand-600 border when recommended; header
padding px 2.5 → 3, pt 2.5 → 3, pb 2 → 4; spacing pass across the
provider identity / package info / sections groups — Divider my
1.5 → 3, section mb 3 → 5, item py 1.5 → 2, heading→first-item 1.5
→ 2.5.
- ComparisonPage mobile: Divider between page header and tab rail;
"Choose a package to view" h2 heading (user-centric copy), used as
aria-labelledby for the tablist; dot indicator below the rail
(8px grey, active 24×8 brand-600 pill) — aria-hidden and tabIndex=-1
so the tab rail above remains the canonical accessible navigation.
Also leaves the Figma capture script in preview-head.html for future
page captures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adopts a single-scroll-container layout for the desktop Comparison page
(motivated by a Figma Make exploration). The page header sits in a
max-width container matching the table's natural width, with flex
spacers either side of the table — when the viewport is wider than
the table, spacers centre it; when a 4th+ package pushes the table
wider than viewport, spacers collapse and the table extends rightward
from the page header's left edge.
- New WizardLayout variant `bleed` — viewport-locked, no inner Container,
main is the single scroll host, back link routed into children,
`data-wizard-scroll` marker for descendants.
- ComparisonTable: fixed 300px column widths exposed as
COMPARISON_TABLE_COL_WIDTH; sticky-left on row-label column across
every per-section mini-table; tiered hover (surface-subtle base /
surface-warm recommended column); recommended column carries a
resting 50%-opacity warm tint; "Not Included" copy replaces em-dash
for unavailable cells in Optionals/Extras sections; CellIconText
helper applies lineHeight: 1 so icon+text rows align optically.
- ComparisonColumnCard: uniform pt: 5 (40px); medium badge (26px) with
star/verified icon; 2px brand-600 border for recommended; provider
name wraps to 2 lines in a reserved 36px bottom-aligned slot so
1-line names keep subsequent content on a consistent baseline; Remove
link always rendered as the same Link element (visibility-hidden when
not applicable) so CTA+footer align across all cards.
- Mackay test data extended to exercise 2-line wrap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace recommended banner with floating badge (star + primary fill)
so CTA buttons align across recommended and non-recommended columns.
- Inline verified icon on recommended cards only (left of provider name,
brand-600). Non-recommended verified providers keep the top badge alone.
- Override recommended card border to brand-600 for consistency with
the rest of the primary system (token default is brand-500).
- Show dash in rating slot when provider has no rating — keeps heights
consistent across the row.
- Invisible Remove placeholder on recommended card so primary CTAs align
with cards that have a visible Remove link.
- Remove link dropped from body2 to caption (12px).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Navigation: add NavItem.children support for desktop dropdown + mobile collapsible sections. Wire Locations (Melbourne, Brisbane, Sydney, South Coast NSW, Central Coast NSW) before FAQ in all HomePage stories.
- HomePage hero: add italic "Trusted by thousands of families across Australia" tagline above h1, widen text container to 990px, use hero-couple.jpg background.
- HomePage features: rename "How it works" to "4 Reasons to use Funeral Arranger", add "Why Use Funeral Arranger" overline, remove placeholder body copy.
- HomePage testimonials: add "Funeral Arranger Reviews" overline above "What families are saying".
- HomePage CTA: promote "Start planning" to primary contained button (medium).
- FuneralFinderV3: remove header + divider so the form starts directly at "How can we help".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hero heading was display3 (same as every section h2), giving no visual
distinction. Now display2 (52px/24px) vs display3 (40px/22px). Still
renders as semantic h1 for SEO.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Increase hero top padding, heading-to-subheading gap, and finder card
side padding on mobile. Scale body1 text to 14px on mobile under display3
headings for better hierarchy contrast. Centre-align "Why Use FA" section
on mobile. Remove arrow from "Start exploring" button.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrate Gitea remotes to git.tensordesign.com.au. Add assetUrl() utility
that resolves image paths from Gitea ParsonsAssets repo when
STORYBOOK_ASSET_BASE is set, enabling images on Chromatic-published
Storybook while keeping local dev unchanged via staticDirs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pushes to backup (full), fa-dev + sheffield (stripped via worktree),
and Chromatic in one command. Replaces ad-hoc push workflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Homepage: add "Why Use FA" text+image section and "Three Ways" feature cards,
reorder sections (logos carousel above discover), apply warm-grey alternating
backgrounds from Figma, unify all section headings to display3 serif, increase
section padding, fix heading hierarchy for SEO, and left-align testimonials.
FuneralFinder V3: responsive CTA (medium on mobile), shorten button to "Search",
bump reassurance text to caption variant, tighten location pin-to-text gap.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New molecule: ComparisonColumnCard — desktop column header card extracted
from ComparisonTable (~150 lines removed from organism)
- New molecule: ComparisonTabCard — mobile tab rail card extracted from
ComparisonPage (shared by V1 and V2)
- CellValue "unknown" restyled: icon+text in neutral grey (was Badge),
InfoOutlinedIcon on right at 14px matching item info icons
- Unverified provider story data: all items set to unknown across all
story files (no dashes in essentials)
- Mobile tab rail: recommended badge (replaces star), package price,
shadow/glow, center-on-select scroll, overflow clipping fixed
- ComparisonPackageCard: added shadow, reduced CTA button to medium
- ComparisonTable first column: inline info icon pattern (non-breaking
space + nowrap span) prevents icon orphaning on line wrap
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The mobile package card was previously duplicated inline in both
ComparisonPage (V2) and ComparisonPageV1 — same ~250-line component
pasted twice. Extract it as a proper molecule so card-level tweaks
land in one file and both pages stay in sync.
New molecule: src/components/molecules/ComparisonPackageCard/ with
component, stories (Verified, Unverified, Recommended,
ItemizedUnavailable), and index. API reuses the existing
ComparisonPackage type from ComparisonTable.
Both pages drop their inline MobilePackageCard + MobileCellValue
helpers and a handful of now-unused imports (Tooltip, Badge, Divider,
several icons, ComparisonCellValue type).
The desktop column header inside ComparisonTable is left inline —
it's tightly coupled to the grid/sticky behaviour and has a floating
verified badge + Remove link that differ meaningfully from the mobile
card. Extracting both variants into one molecule would need an
awkward variant prop for marginal gain.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Archive the current ComparisonPage as V1 (viewable under Archive/ in
Storybook) and build V2 as the new production version. In V2, the
recommended package is prepended instead of appended: it appears as the
first column on desktop and the first tab in the mobile rail. On mobile
the initially active tab is the first user-selected package, not the
recommendation — the recommended tab is surfaced as a visible suggestion
rather than the default view, which felt too upsell-y for the audience.
Both V1 and V2 now use a StarRoundedIcon (brand-600) in the mobile tab
label instead of a text star, so the "recommended" marker reads cleanly
against both selected and unselected tab backgrounds.
See decisions-log D040 for rationale.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add .agent/, .mcp.json, CLAUDE.md, AGENTS.md, GEMINI.md, QUICKSTART.md,
bootstrap.sh, docs/memory/, and docs/reference/ (impeccable, vercel,
workflow guides) to .gitignore. Files remain on disk for local use but
are no longer tracked or pushed to remotes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All three components iterated with user feedback and approved.
Registry updated with final APIs. Session log captures all decisions
from the iteration rounds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hierarchy now matches MiniCard: title → meta → price
- Whole card is clickable (onClick prop) — removed View details link
- Verified badge → icon-only circle in image (matches MiniCard)
- Name truncated at 1 line with tooltip on hover
- No-image fallback shows inline verified icon + text
- Added keyboard support (Enter/Space) and focus ring
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Name is now optional. When omitted, renders a compact single-line
pill with just "From $X" using the bolder name styling. Useful for
denser map views or when provider identity isn't needed at pin level.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Names were too tight against the pill edges, especially on longer
provider names. Bumped token from spacing.2 to spacing.3.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Medium (500) was too thin at 11px — semibold (600) reads better
while still being lighter than the name (700) for hierarchy.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Visually reviewed in Storybook — left-aligned price looked unbalanced.
Centring both lines makes the pin read as a cohesive label rather
than a misaligned mini card.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MiniCard:
- Verified badge → icon-only circle floating in image (top-right)
- Reorder content: title → meta → price → badges → chips
- Truncated titles show tooltip on hover with full text
MapPin: Rethink from price-only pill to two-line label:
- Line 1: Provider name (bold, truncated at 180px)
- Line 2: "From $X" (smaller, secondary colour) — optional
- Communicates who + starting price at a glance
- Verified/unverified palette distinction preserved
- Dot variant removed (name is always required now)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add MiniCard, MapPin, MapPopup to registry. Log session work
including retroactive review completion and new component builds.
Mark all review phases complete in retroactive-review-plan.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Compact provider/venue preview anchored to a MapPin. Image + name +
price + meta row + "View details" link. Downward nub connects to pin.
Drop-shadow filter for floating appearance. Verified badge inside image.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Airbnb-style markers: pill variant (price label + nub) and dot variant
(no price). Verified = brand palette, unverified = neutral grey.
Active state inverts colours + scale-up. Pure CSS for map overlay use.
Keyboard accessible with role="button" and focus ring.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MiniCard: compact vertical card for grids, recommendations, and map
popups. Image + title + optional price/badges/chips/meta. Lighter
than ProviderCard — no verified tiers, no logo. Audit: 20/20.
MapPin tokens added (build next): price-pill markers for map views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a continue button is present (selection gates forward progress),
the radiogroup now communicates that a selection is mandatory.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Human-readable reference for day-to-day use: when to use which tool,
typical flows for page tweaking and component building, workflow quick
reference, and how things change when backend work starts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create AGENTS.md (90 lines) as shared foundation for Claude Code + Antigravity
- Slim CLAUDE.md from 113 to 45 lines (Claude-specific only, references AGENTS.md)
- Slim GEMINI.md from 58 to 26 lines (Antigravity-specific only, references AGENTS.md)
- Add 6 Antigravity workflows in .agent/workflows/ (session-start, preflight, token-sync, visual-qa, build-component, page-review)
- Add docs/reference/cross-tool-workflow.md with task routing, quality gates, file ownership, error mitigation
- Zero content overlap between CLAUDE.md and GEMINI.md (was ~80%)
- File ownership boundaries defined for current phase and future backend work
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Features: remove Card containers and circular icon backgrounds.
Clean icon (brand colour) + heading + description in open grid.
Feels authentic, not template-generated.
CTA: remove warm bg, use default surface with subtle divider above.
Heading in display3, understated placement between testimonials and FAQ.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>