` (lines 27-52) with:
+
+```tsx
+
+
+
+ By Online Form (Anytime)
+
+
+
+
+
+
+
+ By Chat (Anytime)
+
+
+ Click the “Chat Button” at the bottom right to reach our team.
+
+
+
+
+
+
By Phone (9:30-18:00 JST)
+
+
+
+ Toll Free: 0120-660-470
+
+
+ Overseas: +81-3-3560-1006
+
+
+
+
+
+```
+
+Also update the outer card and grid (lines 24-25):
+
+- Line 24: change `p-6 sm:p-8` to `p-5 sm:p-7`
+- Line 25: change `gap-10 lg:gap-12` to `gap-8 lg:gap-10`
+
+And the right column (line 56): change `space-y-6` to `space-y-5`
+
+**Step 2: Verify it builds**
+
+Run: `pnpm type-check`
+
+**Step 3: Visual check**
+
+Check localhost:3000, scroll to bottom contact section. Verify:
+
+- Chat and Phone cards are side-by-side in subtle background cards
+- Phone numbers are inline with labels (more compact)
+- Overall section feels tighter and more organized
+
+**Step 4: Commit**
+
+```bash
+git add apps/portal/src/features/landing-page/components/ContactSection.tsx
+git commit -m "style: improve landing page contact section hierarchy and compactness"
+```
+
+---
+
+### Task 4: Improve PublicContactView layout
+
+**Files:**
+
+- Modify: `apps/portal/src/features/support/views/PublicContactView.tsx`
+
+**Step 1: Tighten header and sidebar**
+
+1. Header section (lines 11-22) — reduce spacing:
+ - Change `mb-12 pt-8` to `mb-10 pt-8`
+ - Change `mb-4` (on heading) to `mb-3`
+
+2. Grid layout (line 25) — reduce gap:
+ - From: `gap-10 mb-16`
+ - To: `gap-8 mb-14`
+
+3. Sidebar cards (lines 32-122) — make more compact:
+ - Change `space-y-6` to `space-y-4`
+ - Change all sidebar card padding from `p-5` to `p-4` (Phone, Chat, Email, Hours, Office cards)
+ - Change icon containers from `h-11 w-11` to `h-10 w-10`
+
+**Step 2: Verify it builds**
+
+Run: `pnpm type-check`
+
+**Step 3: Visual check**
+
+Check localhost:3000/contact. Verify:
+
+- Sidebar cards are slightly more compact
+- Overall page feels tighter
+- Mobile stacking still works cleanly
+
+**Step 4: Commit**
+
+```bash
+git add apps/portal/src/features/support/views/PublicContactView.tsx
+git commit -m "style: tighten contact us page layout and sidebar spacing"
+```
+
+---
+
+### Task 5: Improve PublicSupportView contact section
+
+**Files:**
+
+- Modify: `apps/portal/src/features/support/views/PublicSupportView.tsx:248-264`
+
+**Step 1: Tighten the "Still Need Help?" section**
+
+Replace lines 248-263 with:
+
+```tsx
+{
+ /* Contact Form Fallback */
+}
+
+
+
+
+
+
+
+ Send us a message and we'll get back to you within 24 hours.
+
+
+
+
+
+;
+```
+
+Key changes:
+
+- Icon container `w-12 h-12` → `w-11 h-11`, icon `h-6 w-6` → `h-5 w-5`
+- Section `mb-6` → `mb-5`
+- Icon margin `mb-3` → `mb-2.5`
+- Description text size `text-base` → `text-sm`
+
+**Step 2: Verify it builds**
+
+Run: `pnpm type-check`
+
+**Step 3: Visual check**
+
+Check localhost:3000/support, scroll to bottom. Verify:
+
+- "Still Need Help?" section is slightly tighter
+- Form uses updated shared styling
+
+**Step 4: Commit**
+
+```bash
+git add apps/portal/src/features/support/views/PublicSupportView.tsx
+git commit -m "style: tighten support page contact section spacing"
+```
+
+---
+
+### Task 6: Final verification
+
+**Step 1: Run full lint and type check**
+
+```bash
+pnpm type-check && pnpm lint
+```
+
+Expected: No errors
+
+**Step 2: Visual smoke test all 3 pages**
+
+- localhost:3000 — landing page carousel + bottom contact section
+- localhost:3000/contact — contact us page
+- localhost:3000/support — support page bottom form
+
+Check at mobile (375px) and desktop (1280px) widths.
diff --git a/docs/plans/2026-03-04-trust-strip-redesign.md b/docs/plans/2026-03-04-trust-strip-redesign.md
new file mode 100644
index 00000000..4ef8b3a9
--- /dev/null
+++ b/docs/plans/2026-03-04-trust-strip-redesign.md
@@ -0,0 +1,328 @@
+# TrustStrip Redesign — Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
+
+**Goal:** Replace the minimal icon+text trust strip with a bold stats section featuring large animated count-up numbers, icon circles, vertical dividers, and a gradient background.
+
+**Architecture:** 3-file change — new `useCountUp` hook for the animation, rewritten `TrustStrip.tsx` component, barrel file update. Uses existing `useInView` hook and codebase patterns (cn utility, Tailwind, lucide-react). No new dependencies.
+
+**Tech Stack:** React 19, Tailwind CSS, lucide-react, existing `useInView` hook
+
+---
+
+### Task 1: Create the useCountUp hook
+
+**Files:**
+
+- Create: `apps/portal/src/features/landing-page/hooks/useCountUp.ts`
+
+**Step 1: Write the hook**
+
+Create `apps/portal/src/features/landing-page/hooks/useCountUp.ts`:
+
+```tsx
+import { useEffect, useState } from "react";
+
+/**
+ * useCountUp — Animates a number from 0 to target over a duration.
+ * Respects prefers-reduced-motion. Only runs when enabled is true.
+ */
+export function useCountUp(target: number, duration = 1500, enabled = false): number {
+ const [value, setValue] = useState(0);
+
+ useEffect(() => {
+ if (!enabled) return;
+
+ // Respect prefers-reduced-motion
+ const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
+ if (prefersReduced) {
+ setValue(target);
+ return;
+ }
+
+ let startTime: number | null = null;
+ let rafId: number;
+
+ const animate = (timestamp: number) => {
+ if (!startTime) startTime = timestamp;
+ const elapsed = timestamp - startTime;
+ const progress = Math.min(elapsed / duration, 1);
+
+ // Ease-out cubic for smooth deceleration
+ const eased = 1 - Math.pow(1 - progress, 3);
+ setValue(Math.round(eased * target));
+
+ if (progress < 1) {
+ rafId = requestAnimationFrame(animate);
+ }
+ };
+
+ rafId = requestAnimationFrame(animate);
+ return () => cancelAnimationFrame(rafId);
+ }, [target, duration, enabled]);
+
+ return value;
+}
+```
+
+**Step 2: Export from barrel file**
+
+Modify `apps/portal/src/features/landing-page/hooks/index.ts` — add this line:
+
+```ts
+export { useCountUp } from "./useCountUp";
+```
+
+**Step 3: Verify it builds**
+
+Run: `pnpm type-check`
+Expected: No errors
+
+**Step 4: Commit**
+
+```bash
+git add apps/portal/src/features/landing-page/hooks/useCountUp.ts apps/portal/src/features/landing-page/hooks/index.ts
+git commit -m "feat: add useCountUp hook for animated number transitions"
+```
+
+---
+
+### Task 2: Rewrite TrustStrip component
+
+**Files:**
+
+- Modify: `apps/portal/src/features/landing-page/components/TrustStrip.tsx` (complete rewrite)
+
+**Step 1: Replace TrustStrip.tsx with new implementation**
+
+Rewrite `apps/portal/src/features/landing-page/components/TrustStrip.tsx`:
+
+```tsx
+"use client";
+
+import { Clock, CreditCard, Globe, Users } from "lucide-react";
+import type { LucideIcon } from "lucide-react";
+import { cn } from "@/shared/utils";
+import { useInView, useCountUp } from "@/features/landing-page/hooks";
+
+interface StatItem {
+ icon: LucideIcon;
+ value: number;
+ suffix: string;
+ label: string;
+ delay: number;
+ formatter?: (n: number) => string;
+}
+
+const stats: StatItem[] = [
+ { icon: Clock, value: 20, suffix: "+", label: "Years in Japan", delay: 0 },
+ { icon: Globe, value: 100, suffix: "%", label: "English Support", delay: 100 },
+ {
+ icon: Users,
+ value: 10000,
+ suffix: "+",
+ label: "Customers Served",
+ delay: 200,
+ formatter: (n: number) => n.toLocaleString(),
+ },
+];
+
+function AnimatedStat({ stat, inView }: { stat: StatItem; inView: boolean }) {
+ const count = useCountUp(stat.value, 1500, inView);
+
+ return (
+
+ {stat.formatter ? stat.formatter(count) : count}
+ {stat.suffix}
+
+ );
+}
+
+export function TrustStrip() {
+ const [ref, inView] = useInView();
+
+ return (
+
}
+ aria-label="Company statistics"
+ className={cn(
+ "relative left-1/2 right-1/2 w-screen -translate-x-1/2 py-10 sm:py-12 overflow-hidden transition-all duration-700",
+ inView ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
+ )}
+ >
+ {/* Gradient background */}
+
+
+
+
+ {/* Animated stats */}
+ {stats.map((stat, i) => (
+
+ ))}
+
+ {/* Static stat — Foreign Cards */}
+
+
+
+
+
+ Foreign Cards
+ Accepted
+
+
+
+
+
+ );
+}
+```
+
+Key decisions:
+
+- `AnimatedStat` is a separate component so each stat has its own `useCountUp` instance
+- The 4th stat (Foreign Cards) is rendered separately since it has no numeric animation
+- Desktop: flex row with `border-r` dividers on first 3 items. Mobile: 2-col grid
+- `tabular-nums` prevents layout jitter during count-up animation
+- `formatter` on the 10,000 stat adds comma separators
+
+**Step 2: Verify it builds**
+
+Run: `pnpm type-check`
+Expected: No errors
+
+**Step 3: Visual check**
+
+Open `localhost:3000` and verify:
+
+- 4 stats displayed in a row on desktop, 2x2 grid on mobile
+- Numbers animate from 0 to target when scrolling into view
+- Vertical dividers between first 3 stats on desktop
+- "Foreign Cards / Accepted" shows as static bold text
+- Gradient background blends with hero above
+- Each stat has a primary-tinted circular icon above it
+
+**Step 4: Commit**
+
+```bash
+git add apps/portal/src/features/landing-page/components/TrustStrip.tsx
+git commit -m "feat: redesign TrustStrip with bold animated stats"
+```
+
+---
+
+### Task 3: Stagger the count-up animations
+
+The current implementation starts all counters simultaneously. Add stagger delays.
+
+**Files:**
+
+- Modify: `apps/portal/src/features/landing-page/hooks/useCountUp.ts`
+- Modify: `apps/portal/src/features/landing-page/components/TrustStrip.tsx`
+
+**Step 1: Add delay parameter to useCountUp**
+
+In `useCountUp.ts`, change the signature and add a delay before animation starts:
+
+```tsx
+export function useCountUp(target: number, duration = 1500, enabled = false, delay = 0): number {
+```
+
+Update the effect body — wrap the animation start in a `setTimeout`:
+
+```tsx
+useEffect(() => {
+ if (!enabled) return;
+
+ const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
+ if (prefersReduced) {
+ setValue(target);
+ return;
+ }
+
+ let startTime: number | null = null;
+ let rafId: number;
+ let timeoutId: ReturnType
;
+
+ const animate = (timestamp: number) => {
+ if (!startTime) startTime = timestamp;
+ const elapsed = timestamp - startTime;
+ const progress = Math.min(elapsed / duration, 1);
+ const eased = 1 - Math.pow(1 - progress, 3);
+ setValue(Math.round(eased * target));
+
+ if (progress < 1) {
+ rafId = requestAnimationFrame(animate);
+ }
+ };
+
+ timeoutId = setTimeout(() => {
+ rafId = requestAnimationFrame(animate);
+ }, delay);
+
+ return () => {
+ clearTimeout(timeoutId);
+ cancelAnimationFrame(rafId);
+ };
+}, [target, duration, enabled, delay]);
+```
+
+**Step 2: Pass delay from TrustStrip**
+
+In `AnimatedStat`, update the `useCountUp` call:
+
+```tsx
+function AnimatedStat({ stat, inView }: { stat: StatItem; inView: boolean }) {
+ const count = useCountUp(stat.value, 1500, inView, stat.delay);
+```
+
+**Step 3: Verify it builds**
+
+Run: `pnpm type-check`
+Expected: No errors
+
+**Step 4: Visual check**
+
+Open `localhost:3000`, scroll to trust strip. The 3 animated numbers should start counting up in sequence: "20+" first, "100%" ~100ms later, "10,000+" ~200ms later. The stagger should feel subtle but add polish.
+
+**Step 5: Commit**
+
+```bash
+git add apps/portal/src/features/landing-page/hooks/useCountUp.ts apps/portal/src/features/landing-page/components/TrustStrip.tsx
+git commit -m "feat: add staggered delay to count-up animations"
+```
+
+---
+
+### Task 4: Final verification
+
+**Step 1: Run type check and lint**
+
+Run: `pnpm type-check`
+Expected: No errors
+
+**Step 2: Visual smoke test**
+
+Check `localhost:3000` at:
+
+- Desktop (1280px): 4 stats in a row, dividers, gradient bg, count-up animation
+- Tablet (768px): same row, slightly smaller numbers
+- Mobile (375px): 2x2 grid, no dividers, animation still works
+
+**Step 3: Accessibility check**
+
+- Tab through the page — stats section should be announced as "Company statistics"
+- Set `prefers-reduced-motion: reduce` in browser DevTools — numbers should show final values immediately without animation