140 Commits

Author SHA1 Message Date
belviskhoremk
c06891eebb Add design spec for Phase 2 sub-project A: backend foundation 2026-08-04 23:39:33 +00:00
belviskhoremk
42c0cf0f46 Redesign footer to fix layout and add visual hierarchy
The old flex layout with justify-content: space-between pushed its
two children to the far edges on wide screens, leaving a large dead
void in the middle. Replaced with a centered, max-width three-column
grid (brand, contact, navigate) with a script wordmark, gold section
labels, a divider separating it from the banner above, and a
copyright line.
2026-08-04 00:26:35 +00:00
belviskhoremk
3d0a275d67 Add real product, style, portrait, and testimonial photography
Sourced from Pexels (free for commercial use, no attribution
required) to complete the image wiring added in the visual overhaul.
Fills the 18 image slots that were previously deferred (products,
signature styles, About Mira portrait, testimonial avatars).
2026-08-04 00:07:43 +00:00
belviskhoremk
1e9609ce23 Replace placeholder salon rules with Mira's real policy text
Kept in French to match how Mira actually messages clients. Updated
RuleIcon's icon set to match the real policy categories (deposit,
hair prep, extensions, lateness, guests, payment) in place of the
placeholder categories.
2026-08-03 23:48:54 +00:00
belviskhoremk
c4180a90bf fix: address final review findings — code-split Home's 3D bundle, bound card widths, fix Book step transition, cleanup
- Lazy-load Home in App.tsx so three/@react-three/fiber (~238 kB gzip) only ships to the
  Home route, not to Shop/Book/Rules.
- Add max-width: 260px to ProductCard/ServiceCard so real images won't collapse Home/Book
  grid layouts.
- Restore AnimatePresence mode="wait" in Book.tsx to eliminate the exit/enter double-stack
  during step transitions, updating the three Book.test.tsx assertions that raced the
  transition to findBy* queries.
- Hero3DScene: drop the meaningless "static" className string in favor of a dedicated
  data-testid, add aria-hidden to the reduced-motion fallback branch, and remove the
  unused @react-three/drei dependency (adding @types/three directly since it was only
  present transitively via drei).
2026-08-03 23:40:32 +00:00
belviskhoremk
585c77ba42 feat: add per-rule icons and staggered scroll-in to Rules page
Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 23:15:44 +00:00
belviskhoremk
801c4c028f feat: add step progress indicator and animated transitions to Book
Adds StepProgress component showing 4 labeled booking steps (Service,
Date & Time, Contact, Confirmed) and wires it into Book.tsx alongside
framer-motion AnimatePresence/motion.div step transitions.

Deviates from literal brief in two ways, both to avoid known issues:
- Guards the transition with useReducedMotion() (duration: 0 when
  prefers-reduced-motion is set), matching the fix pattern already
  applied to Home.tsx and Shop.tsx after prior review round-trips.
- Drops AnimatePresence's mode="wait" in favor of the default (sync)
  mode: with mode="wait", the incoming step's DOM doesn't mount until
  the outgoing step's exit animation finishes, which broke existing
  synchronous Testing Library queries in Book.test.tsx (real 250ms
  exit animations in jsdom, no fake timers). Sync mode mounts the new
  step immediately while both fade, preserving test synchronicity.

Also updates Book.test.tsx's confirmation assertion since the old
"You're booked!" heading is gone (page now always shows the shared
"Book an Appointment" heading and StepProgress; only the body swaps).
2026-08-03 23:11:29 +00:00
belviskhoremk
3f82e759cb fix: make Shop's sliding filter pill respect prefers-reduced-motion 2026-08-03 23:07:06 +00:00
belviskhoremk
7cd84f1c66 feat: animate Shop's active category filter with a sliding pill indicator 2026-08-03 23:04:38 +00:00
belviskhoremk
e24c1c7be7 fix: make Home's portrait parallax respect prefers-reduced-motion
The About section's portrait image now checks useReducedMotion() and
disables parallax scroll motion when the user has set OS-level reduced
motion preferences.

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 23:02:21 +00:00
belviskhoremk
726893ab87 feat: add portrait with parallax, real product cards, and testimonial avatars to Home 2026-08-03 22:59:25 +00:00
belviskhoremk
c690c8292a feat: render service images with hover-zoom in ServiceCard
Claude-Session: https://claude.ai/code/session
2026-08-03 22:56:12 +00:00
belviskhoremk
8be76f77a4 feat: render product images with hover-zoom in ProductCard 2026-08-03 22:53:28 +00:00
belviskhoremk
12beaa990e feat: replace CSS hero motif with a real WebGL 3D braided-crown scene
Adds Hero3DScene, a procedurally-built rotating braid mesh rendered via
@react-three/fiber, replacing the flat CSS-circle Hero3D component. Falls
back to a static gradient circle under prefers-reduced-motion, matching the
old component's fallback behavior.

Also adds a ResizeObserver mock to the test setup, required by
@react-three/fiber's Canvas (via react-use-measure) in jsdom, which doesn't
implement it natively.
2026-08-03 22:49:24 +00:00
belviskhoremk
6244ef11ce chore: add three, @react-three/fiber, @react-three/drei for the 3D hero 2026-08-03 22:41:39 +00:00
belviskhoremk
36569e224c Add implementation plan for frontend visual overhaul 2026-08-03 22:37:09 +00:00
belviskhoremk
bd81222922 Add design spec for frontend visual overhaul (3D hero, imagery, page polish) 2026-08-03 22:30:56 +00:00
belviskhoremk
c458ace903 Merge branch 'worktree-braids-phase1'
# Conflicts:
#	README.md
#	src/App.test.tsx
#	src/App.tsx
#	src/test/setup.ts
2026-08-03 20:43:58 +00:00
belviskhoremk
9f3e037cdc fix: address final review findings — Hero3D static class, InquiryModal a11y, date guards, shared email validation, README
Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 20:40:16 +00:00
belviskhoremk
251a6558fb polish: add responsive breakpoints for nav, home, and shop 2026-08-03 20:30:09 +00:00
belviskhoremk
cbcefbc559 feat: add Home landing page assembling all sections 2026-08-03 20:20:22 +00:00
belviskhoremk
7502c160eb feat: add Rules page 2026-08-03 20:15:56 +00:00
belviskhoremk
c733a5afa9 feat: add Book page with the full mock-data booking flow 2026-08-03 17:56:01 +00:00
belviskhoremk
358b5121f0 fix: make useBooking submit() validate synchronously instead of racing setState's updater 2026-08-03 17:51:45 +00:00
belviskhoremk
a270c33c73 feat: add useBooking hook for the booking flow state machine 2026-08-03 17:49:42 +00:00
belviskhoremk
f4687105bb fix: use globalThis instead of Node-only global in test setup to unblock the TypeScript build
Replace 'global.IntersectionObserver' with 'globalThis.IntersectionObserver' to fix
TS2304 "Cannot find name 'global'" error. globalThis is the standard environment-agnostic
reference that type-checks cleanly in browser-targeted tsconfig. Runtime behavior
identical to global in Node/jsdom contexts.

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:39:30 +00:00
belviskhoremk
0795efc421 fix: apply CSS module class for active Shop category filter
Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:37:14 +00:00
belviskhoremk
698f79daf6 feat: add Shop page with category filter and product inquiries
Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:33:55 +00:00
belviskhoremk
cdc74488cd feat: add InquiryModal for product inquiries
Implements a modal component for collecting product inquiries with name, email, and notes fields. Validates name (required) and email (must contain @) client-side, displays inline error messages for invalid input, and shows a confirmation message on valid submit.

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:30:52 +00:00
belviskhoremk
88379caee2 feat: add ProductCard and ServiceCard components
Implement ProductCard component with:
- Renders product details (name, price, description)
- "Ask about this" button disabled when out of stock
- Shows "Currently unavailable" badge when out of stock
- Calls onInquire callback when clicked

Implement ServiceCard component with:
- Renders service details (name, formatted duration, price)
- Clickable button card that calls onSelect with service id
- formatDuration helper for human-readable time format

Both components include CSS modules with hover effects and proper styling.
All 4 tests pass (2 for each component).

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:27:31 +00:00
belviskhoremk
8c88f2a891 fix: isolate Hero3D reduced-motion test from framer-motion's module-level cache
framer-motion's useReducedMotion() hook caches its result at the module level
and never re-reads window.matchMedia on subsequent calls. This caused the second
test to fail because the cache was locked to the first test's matchMedia mock.

Fixed by using vi.doMock() with vi.resetModules() to mock useReducedMotion
directly with the desired value for each test, ensuring each test runs with a
fresh module context where the hook returns the expected value.

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:22:54 +00:00
belviskhoremk
e3cdb743ab feat: add Hero3D scroll-driven rotating motif component
- Implements Hero3D component with CSS 3D transforms
- Uses framer-motion's useScroll/useTransform for scroll-linked rotation
- Respects prefers-reduced-motion preference for static rendering
- Component structure: wrapper with perspective, inner motif with 3D rotation
- Test setup: added window.matchMedia mock for framer-motion compatibility

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 17:18:42 +00:00
belviskhoremk
ede4387ab3 feat: add shared Layout wrapping Nav and Footer around all routes
- Create Layout component that renders Nav > Outlet > Footer
- Wire Layout as parent route in App.tsx to wrap all page routes
- Update App.test.tsx to verify Nav/Footer render on every route

Claude-Session: https://claude.ai/code
2026-08-03 17:07:35 +00:00
belviskhoremk
df3bff9ed3 feat: add Nav and Footer components 2026-08-03 17:04:33 +00:00
belviskhoremk
619d5a506e feat: add ScrollReveal motion wrapper component
Implement ScrollReveal component that fades and rises sections into view
on scroll with framer-motion. Respects prefers-reduced-motion by
rendering children unanimated when that setting is enabled.

- Add ScrollReveal component with fade+rise animation on scroll
- Add test coverage for both animated and reduced-motion paths
- Add IntersectionObserver mock to test setup

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-03 16:59:56 +00:00
belviskhoremk
d920651a09 feat: add mock data for products, services, availability, and rules 2026-08-03 16:56:49 +00:00
belviskhoremk
4771d3ead7 chore: set up Vitest, routing, and design tokens
Includes the base Vite+React+TS scaffold files (package.json, index.html,
tsconfigs, etc.) which had never been committed to git.
2026-08-03 16:53:05 +00:00
belviskhoremk
adaaa8a3f2 chore: set up Vitest, routing, and design tokens 2026-08-03 16:42:58 +00:00
belviskhoremk
0ae6ceab62 Add Phase 1 implementation plan for Braids by Mira public site 2026-08-03 16:20:18 +00:00
belviskhoremk
95d3845cf3 Add Phase 1 design spec for Braids by Mira public site 2026-08-03 16:14:48 +00:00