diff --git a/src/app/[country]/[locale]/(storefront)/account/register/page.tsx b/src/app/[country]/[locale]/(storefront)/account/register/page.tsx
index 79fae3f3..1a1ab322 100644
--- a/src/app/[country]/[locale]/(storefront)/account/register/page.tsx
+++ b/src/app/[country]/[locale]/(storefront)/account/register/page.tsx
@@ -252,7 +252,7 @@ export default function RegisterPage() {
{t("alreadyHaveAccount")}{" "}
{t("signIn")}
diff --git a/src/app/[country]/[locale]/(storefront)/account/reset-password/page.tsx b/src/app/[country]/[locale]/(storefront)/account/reset-password/page.tsx
index fbc558d8..f17ca698 100644
--- a/src/app/[country]/[locale]/(storefront)/account/reset-password/page.tsx
+++ b/src/app/[country]/[locale]/(storefront)/account/reset-password/page.tsx
@@ -107,7 +107,7 @@ export default function ResetPasswordPage() {
router.push(`${basePath}/account`)}
+ onClick={() => router.push(`${basePath}/account/login`)}
>
{t("signIn")}
@@ -223,7 +223,7 @@ export default function ResetPasswordPage() {
{t("backToSignIn")}
diff --git a/src/app/[country]/[locale]/(storefront)/cart/page.tsx b/src/app/[country]/[locale]/(storefront)/cart/page.tsx
index 9ef8e6da..b02bb024 100644
--- a/src/app/[country]/[locale]/(storefront)/cart/page.tsx
+++ b/src/app/[country]/[locale]/(storefront)/cart/page.tsx
@@ -6,6 +6,7 @@ import Link from "next/link";
import { usePathname } from "next/navigation";
import { useTranslations } from "next-intl";
import { useEffect, useRef } from "react";
+import { CartSkeleton } from "@/components/cart/CartSkeleton";
import { Button } from "@/components/ui/button";
import { ProductImage } from "@/components/ui/product-image";
import { QuantityPicker } from "@/components/ui/quantity-picker";
@@ -42,18 +43,7 @@ export default function CartPage() {
};
if (loading) {
- return (
-
-
-
-
- {[1, 2, 3].map((i) => (
-
- ))}
-
-
-
- );
+ return ;
}
if (!cart || !cart.items || cart.items.length === 0) {
diff --git a/src/components/account/AccountDashboardSkeleton.tsx b/src/components/account/AccountDashboardSkeleton.tsx
new file mode 100644
index 00000000..74863ef5
--- /dev/null
+++ b/src/components/account/AccountDashboardSkeleton.tsx
@@ -0,0 +1,34 @@
+import { Card, CardContent } from "@/components/ui/card";
+
+/**
+ * Skeleton mirroring `account/page.tsx` (dashboard overview):
+ * - h1 `text-2xl` (32px line-height), `mb-6`
+ * - 2×2 grid of Cards (`grid-cols-1 md:grid-cols-2 gap-6`), each Card wraps
+ * CardContent (py-0) with an icon box (`p-3 rounded-xl`, size-6 icon = 48px)
+ * and a text column (h2 text-lg + mt-1 description text-sm)
+ */
+export function AccountDashboardSkeleton() {
+ return (
+
+ {/* h1 Account overview */}
+
+
+
+ {[0, 1, 2, 3].map((i) => (
+
+
+ {/* Icon box: p-3 (12px) + size-6 icon (24px) = 48px square */}
+
+
+ {/* h2 text-lg = 28px line-height */}
+
+ {/* description text-sm, mt-1 */}
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/account/AddressesSkeleton.tsx b/src/components/account/AddressesSkeleton.tsx
new file mode 100644
index 00000000..4bd16a46
--- /dev/null
+++ b/src/components/account/AddressesSkeleton.tsx
@@ -0,0 +1,54 @@
+/**
+ * Skeleton mirroring `account/addresses/page.tsx` + `AddressManagement.tsx`:
+ * - Title bar: h1 `text-2xl` (32px) + mb-6
+ * - Add button row: mb-6, default Button h-11
+ * - Grid `grid-cols-1 md:grid-cols-2 gap-4` of address cards
+ * - Each card: `rounded-xl border p-6` with `flex justify-between items-start`
+ * → address block (text-sm space-y-0.5, 4 lines) + Edit/Delete buttons
+ */
+function AddressCardSkeleton() {
+ return (
+
+
+ {/* Address lines: text-sm (20px) space-y-0.5 (2px) */}
+
+ {/* full_name font-medium */}
+
+ {/* address1 */}
+
+ {/* city, state zip */}
+
+ {/* country */}
+
+
+ {/* Edit (link sm) + Delete (destructive sm), gap-2 */}
+
+
+
+ );
+}
+
+export function AddressesSkeleton() {
+ return (
+
+ {/* Title row */}
+
+
+ {/* Add address button (default size h-11) */}
+
+
+ {/* Grid of address cards — 2 items */}
+
+
+ );
+}
diff --git a/src/components/account/AuthFallbackSkeleton.tsx b/src/components/account/AuthFallbackSkeleton.tsx
new file mode 100644
index 00000000..4c66aae7
--- /dev/null
+++ b/src/components/account/AuthFallbackSkeleton.tsx
@@ -0,0 +1,16 @@
+/**
+ * Generic fallback skeleton for auth pages without a dedicated skeleton yet
+ * (forgot-password, reset-password). Kept minimal and centered to match the
+ * `max-w-md mx-auto py-16` container used by those pages.
+ */
+export function AuthFallbackSkeleton(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/components/account/ContentSkeleton.tsx b/src/components/account/ContentSkeleton.tsx
new file mode 100644
index 00000000..5b21f1bd
--- /dev/null
+++ b/src/components/account/ContentSkeleton.tsx
@@ -0,0 +1,14 @@
+/**
+ * Generic fallback skeleton for protected account sub-pages that don't yet have
+ * a dedicated skeleton (mirrors a simple header + two content blocks layout).
+ */
+export function ContentSkeleton(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/components/account/CreditCardsSkeleton.tsx b/src/components/account/CreditCardsSkeleton.tsx
new file mode 100644
index 00000000..273631a2
--- /dev/null
+++ b/src/components/account/CreditCardsSkeleton.tsx
@@ -0,0 +1,47 @@
+/**
+ * Skeleton mirroring `account/credit-cards/page.tsx` + `CreditCardList.tsx`:
+ * - h1 `text-2xl font-bold` (32px) + `mb-6`
+ * - Card list: `space-y-4` of `rounded-xl border p-6` items with
+ * [PaymentIcon(48x32) + label/expiry] | [Remove button h-9]
+ * - Help text footer: `mt-6 p-4 bg-gray-50 rounded-xl` with text-sm
+ */
+function CreditCardItemSkeleton() {
+ return (
+
+
+
+ {/* PaymentIcon width=48, flatRounded aspect ≈ 48×30 */}
+
+
+ {/* "Visa ending in 4242" text-sm */}
+
+ {/* expires text-xs = 16px */}
+
+
+
+ {/* Remove button size="sm" = h-9 */}
+
+
+
+ );
+}
+
+export function CreditCardsSkeleton() {
+ return (
+
+ {/* h1 Payment methods */}
+
+
+ {/* Card list space-y-4 — 2 items */}
+
+
+
+
+
+ {/* Help text footer */}
+
+
+ );
+}
diff --git a/src/components/account/ForgotPasswordFormSkeleton.tsx b/src/components/account/ForgotPasswordFormSkeleton.tsx
new file mode 100644
index 00000000..2d48aa1e
--- /dev/null
+++ b/src/components/account/ForgotPasswordFormSkeleton.tsx
@@ -0,0 +1,41 @@
+import {
+ Card,
+ CardContent,
+ CardFooter,
+ CardHeader,
+} from "@/components/ui/card";
+
+/**
+ * Skeleton mirroring `account/forgot-password/page.tsx` (request form state):
+ * Card (py-6 gap-6) → Header (title text-2xl `leading-none` = 24px + description
+ * text-sm = 20px) → Content (space-y-4: email field + submit h-13) → Footer
+ * (centered text-sm "back to sign in" link).
+ */
+export function ForgotPasswordFormSkeleton() {
+ return (
+
+
+
+
+
+
+
+
+
+ {/* Email field: label text-sm (h-5) + Input h-11 */}
+
+ {/* Submit Button size="lg" h-13 rounded-lg */}
+
+
+
+
+ {/* "Back to sign in" link text-sm */}
+
+
+
+
+ );
+}
diff --git a/src/components/account/GiftCardsSkeleton.tsx b/src/components/account/GiftCardsSkeleton.tsx
new file mode 100644
index 00000000..7e815b3f
--- /dev/null
+++ b/src/components/account/GiftCardsSkeleton.tsx
@@ -0,0 +1,71 @@
+/**
+ * Skeleton mirroring `account/gift-cards/page.tsx` + `GiftCardList.tsx`:
+ * - h1 `text-2xl font-bold` (32px) + `mb-6`
+ * - Active cards section: h2 text-lg (28px) + `mb-4`, then `space-y-4` list of GiftCardItems
+ * - Each item: `rounded-xl border p-6` with header row (code + copy + status badge | amount right)
+ * and progress bar section
+ * - Help text footer: `mt-6 p-4 bg-gray-50 rounded-xl` with text-sm
+ */
+function GiftCardItemSkeleton() {
+ return (
+
+ {/* Header row */}
+
+
+
+ {/* code font-mono text-lg = 28px */}
+
+ {/* Copy button size="sm" = h-9 */}
+
+ {/* status badge: px-2.5 py-0.5 rounded-lg text-xs ≈ 20px */}
+
+
+ {/* expires p text-sm mt-1 */}
+
+
+
+ {/* amount_remaining text-2xl = 32px */}
+
+ {/* "remaining" label text-sm */}
+
+
+
+
+ {/* Progress bar section mb-4 */}
+
+
+ {/* bar h-2 rounded-lg */}
+
+ {/* percent used text-xs = 16px */}
+
+
+
+ );
+}
+
+export function GiftCardsSkeleton() {
+ return (
+
+ {/* h1 Gift cards */}
+
+
+ {/* Active cards section */}
+
+ {/* h2 text-lg font-semibold + mb-4 */}
+
+
+
+
+
+
+
+ {/* Help text footer: mt-6 p-4 bg-gray-50 rounded-xl */}
+
+
+ );
+}
diff --git a/src/components/account/LoginFormSkeleton.tsx b/src/components/account/LoginFormSkeleton.tsx
new file mode 100644
index 00000000..f95dc268
--- /dev/null
+++ b/src/components/account/LoginFormSkeleton.tsx
@@ -0,0 +1,44 @@
+import {
+ Card,
+ CardContent,
+ CardFooter,
+ CardHeader,
+} from "@/components/ui/card";
+
+/**
+ * Skeleton mirroring the login form in `account/login/page.tsx`:
+ * Card (py-6 gap-6) → Header (title text-2xl + description text-sm) →
+ * Content (space-y-4: email field, password field, forgot link, submit h-13) →
+ * Footer (centered text-sm).
+ */
+export function LoginFormSkeleton(): React.JSX.Element {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/account/OrdersListSkeleton.tsx b/src/components/account/OrdersListSkeleton.tsx
new file mode 100644
index 00000000..b51e91dd
--- /dev/null
+++ b/src/components/account/OrdersListSkeleton.tsx
@@ -0,0 +1,61 @@
+/**
+ * Skeleton mirroring `account/orders/page.tsx` + `OrderList.tsx`:
+ * - h1 `text-2xl font-bold` (32px line-height) + `mb-6`
+ * - Table card (`rounded-xl border`): thead bg-gray-50 with 6 cols (text-xs uppercase, py-3),
+ * tbody with 3 rows (px-6 py-4, text-sm or rounded-lg badges).
+ */
+export function OrdersListSkeleton() {
+ return (
+
+ {/* h1 Order history */}
+
+
+
+
+
+
+
+ {/* 6 columns: Order / Date / Payment / Shipment / Total / Actions */}
+ {[0, 1, 2, 3, 4, 5].map((i) => (
+
+
+
+ ))}
+
+
+
+ {[0, 1, 2].map((i) => (
+
+ {/* #number (text-sm) */}
+
+
+
+ {/* date */}
+
+
+
+ {/* payment badge: px-2.5 py-0.5 rounded-lg text-xs ≈ 20px */}
+
+
+
+ {/* shipment badge */}
+
+
+
+ {/* total (right) */}
+
+
+
+ {/* view link (right) */}
+
+
+
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/src/components/account/ProfileSkeleton.tsx b/src/components/account/ProfileSkeleton.tsx
new file mode 100644
index 00000000..09cbef70
--- /dev/null
+++ b/src/components/account/ProfileSkeleton.tsx
@@ -0,0 +1,60 @@
+/**
+ * Skeleton mirroring `account/profile/page.tsx`:
+ * - h1 (text-2xl = 32px line-height, mb-6)
+ * - Form card: p-6 space-y-6 (first/last grid + email field), footer with save button
+ * - Account info card: header (text-lg = 28px) + 2-col grid of label/value pairs
+ */
+export function ProfileSkeleton(): React.JSX.Element {
+ return (
+
+ {/* h1 Profile */}
+
+
+ {/* Form card */}
+
+
+ {/* first / last name grid */}
+
+ {/* email */}
+
+
+ {/* Save button footer */}
+
+
+
+ {/* Account info card */}
+
+
+ {/* h2 Account Information (text-lg = 28px) */}
+
+
+
+
+
+ );
+}
diff --git a/src/components/account/RegisterFormSkeleton.tsx b/src/components/account/RegisterFormSkeleton.tsx
new file mode 100644
index 00000000..dee1ea09
--- /dev/null
+++ b/src/components/account/RegisterFormSkeleton.tsx
@@ -0,0 +1,62 @@
+import {
+ Card,
+ CardContent,
+ CardFooter,
+ CardHeader,
+} from "@/components/ui/card";
+
+/**
+ * Skeleton mirroring the register form in `account/register/page.tsx`:
+ * Card → Header → Content (space-y-4: first/last name grid, email, password,
+ * password confirmation, policy consent, submit) → Footer.
+ */
+export function RegisterFormSkeleton() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Policy consent: checkbox (size-4.5) + wrapped text (text-sm 2 lines = 40px) */}
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/account/ResetPasswordFormSkeleton.tsx b/src/components/account/ResetPasswordFormSkeleton.tsx
new file mode 100644
index 00000000..94d24e36
--- /dev/null
+++ b/src/components/account/ResetPasswordFormSkeleton.tsx
@@ -0,0 +1,44 @@
+import {
+ Card,
+ CardContent,
+ CardFooter,
+ CardHeader,
+} from "@/components/ui/card";
+
+/**
+ * Skeleton mirroring `account/reset-password/page.tsx` (reset form state):
+ * Card → Header (title text-2xl `leading-none` = 24px + description text-sm = 20px)
+ * → Content (space-y-4: new password field, confirm password field, submit h-13)
+ * → Footer (centered "back to sign in" link text-sm).
+ */
+export function ResetPasswordFormSkeleton() {
+ return (
+
+
+
+
+
+
+
+
+ {/* New password: label + Input h-11 */}
+
+ {/* Confirm password: label + Input h-11 */}
+
+ {/* Submit Button size="lg" h-13 rounded-lg */}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/account/SidebarUserInfoSkeleton.tsx b/src/components/account/SidebarUserInfoSkeleton.tsx
new file mode 100644
index 00000000..e68606f7
--- /dev/null
+++ b/src/components/account/SidebarUserInfoSkeleton.tsx
@@ -0,0 +1,16 @@
+/**
+ * Skeleton for the sidebar user-info block inside `AccountShell`.
+ * Matches adjacent line-heights (text-base = 24px, text-sm = 20px, no gap).
+ */
+export function SidebarUserInfoSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/cart/CartDrawer.tsx b/src/components/cart/CartDrawer.tsx
index 525399bc..56ad01d9 100644
--- a/src/components/cart/CartDrawer.tsx
+++ b/src/components/cart/CartDrawer.tsx
@@ -5,6 +5,7 @@ import Link from "next/link";
import { usePathname } from "next/navigation";
import { useTranslations } from "next-intl";
import { useEffect, useRef } from "react";
+import { CartDrawerSkeleton } from "@/components/cart/CartDrawerSkeleton";
import { Button } from "@/components/ui/button";
import { ProductImage } from "@/components/ui/product-image";
import { QuantityPicker } from "@/components/ui/quantity-picker";
@@ -98,17 +99,7 @@ export function CartDrawer() {
{loading ? (
-
- {[1, 2].map((i) => (
-
- ))}
-
+
) : isEmpty ? (
+ {[0, 1].map((i) => (
+
+ ))}
+
+ );
+}
diff --git a/src/components/cart/CartSkeleton.tsx b/src/components/cart/CartSkeleton.tsx
new file mode 100644
index 00000000..86a0c5d7
--- /dev/null
+++ b/src/components/cart/CartSkeleton.tsx
@@ -0,0 +1,78 @@
+/**
+ * Skeleton mirroring `(storefront)/cart/page.tsx` (2-item scenario):
+ * - h1 `text-3xl font-bold` (36px line-height), `mb-8`
+ * - Grid `lg:grid-cols-3 gap-8`: items card (col-span-2) + summary sidebar (col-span-1)
+ * - Items: `rounded-xl border divide-y`, each row `p-6 flex gap-6` with
+ * image (w-24 h-24), details (title text-lg + options text-sm + price text-lg),
+ * and actions (QuantityPicker h-9 + Remove button sm h-9)
+ * - Summary: `sticky top-24 p-6 rounded-xl border` with header, subtotal/total rows,
+ * and CTA buttons (Button size="lg" h-13 + Button variant="link" h-11)
+ */
+export function CartSkeleton() {
+ return (
+
+ {/* h1 "Shopping cart" — text-3xl line-height 36px, mb-8 */}
+
+
+
+ {/* Items list (2 rows) */}
+
+
+ {[0, 1].map((i) => (
+
+ {/* Image w-24 h-24 rounded-xl */}
+
+
+ {/* Details */}
+
+ {/* title text-lg = 28px */}
+
+ {/* options text-sm, mt-1 */}
+
+ {/* price text-lg, mt-2 */}
+
+
+
+ {/* Quantity + Remove */}
+
+ {/* QuantityPicker ~h-9 */}
+
+ {/* Remove Button size="sm" h-9 */}
+
+
+
+ ))}
+
+
+
+ {/* Summary sidebar */}
+
+
+ {/* h2 text-lg = 28px */}
+
+
+
+ {/* Subtotal row — text-base line-height 24 */}
+
+ {/* Total row — border-t pt-4, text-lg = 28 */}
+
+
+
+
+ {/* Button size="lg" h-13 rounded-lg */}
+
+ {/* Button variant="link" size default h-11 */}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/checkout/CheckoutPageSkeleton.tsx b/src/components/checkout/CheckoutPageSkeleton.tsx
new file mode 100644
index 00000000..12e88849
--- /dev/null
+++ b/src/components/checkout/CheckoutPageSkeleton.tsx
@@ -0,0 +1,73 @@
+/**
+ * Skeleton mirroring `checkout/[id]/page.tsx` main content:
+ * - Contact (h2 text-lg + mb-3 + email input, mb-6)
+ * - Shipping address (h2 + 7 rows: country, first/last grid, address, apartment,
+ * city/state/zip grid, phone — all h-11 with `gap-3`)
+ * - Shipping method (mt-6, h2 + gray placeholder box)
+ * - Payment (mt-6, h2 + subline + note + bordered container with header + form area)
+ * - Pay now button (mt-8, h-[54px] rounded-sm)
+ *
+ * Headings use `text-lg font-bold` (28px = h-7), inputs `h-11`, button `h-[54px]`.
+ * Company and policy consent intentionally omitted (optional / guest-only — avoids
+ * layout shift across authed vs guest flows).
+ */
+export function CheckoutPageSkeleton() {
+ return (
+
+ {/* Contact */}
+
+
+ {/* Shipping address */}
+
+
+
+ {/* Country */}
+
+ {/* First / Last */}
+
+ {/* Address */}
+
+ {/* Apartment */}
+
+ {/* City / State / Zip */}
+
+ {/* Phone */}
+
+
+
+
+ {/* Shipping method */}
+
+
+ {/* gray placeholder box (px-4 py-3.5 + text-sm line 20 = ~48px) */}
+
+
+
+ {/* Payment method */}
+
+
+ {/* "Secure transactions" subline (text-sm, mt-0.5) */}
+
+ {/* "Test card note" (text-xs, mb-3) */}
+
+
+
+
+ {/* Pay now button (h-[54px]) */}
+
+
+ );
+}
diff --git a/src/components/layout/AccountLink.tsx b/src/components/layout/AccountLink.tsx
new file mode 100644
index 00000000..9ea4f0e5
--- /dev/null
+++ b/src/components/layout/AccountLink.tsx
@@ -0,0 +1,34 @@
+"use client";
+
+import Link from "next/link";
+import type { ComponentProps } from "react";
+import { useAuth } from "@/contexts/AuthContext";
+
+type AccountLinkProps = Omit
, "href"> & {
+ basePath: string;
+};
+
+/**
+ * Account link that routes directly to the correct page based on auth state:
+ * - authenticated → `/account` (dashboard)
+ * - unauthenticated → `/account/login` (skip the layout's redirect hop)
+ * - still loading → `/account` (safe default; layout handles the redirect)
+ *
+ * Accepts all props a `next/link` ` ` accepts (except `href`) and forwards
+ * them onto the underlying Link so it composes correctly with Radix Slot
+ * consumers like `` and ``, which inject
+ * className / onClick / data-state / ref onto their child.
+ */
+export function AccountLink({
+ basePath,
+ ...props
+}: AccountLinkProps): React.JSX.Element {
+ const { isAuthenticated, loading } = useAuth();
+
+ const href =
+ loading || isAuthenticated
+ ? `${basePath}/account`
+ : `${basePath}/account/login`;
+
+ return ;
+}
diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx
index f0cd61a0..788292ef 100644
--- a/src/components/layout/Footer.tsx
+++ b/src/components/layout/Footer.tsx
@@ -1,6 +1,7 @@
import type { Category } from "@spree/sdk";
import Link from "next/link";
import { getTranslations } from "next-intl/server";
+import { AccountLink } from "@/components/layout/AccountLink";
import { POLICY_LINKS } from "@/lib/constants/policies";
import { getStoreDescription, getStoreName } from "@/lib/store";
@@ -101,12 +102,12 @@ export async function Footer({
-
{t("myAccount")}
-
+
-
+
-
+
diff --git a/src/components/layout/MobileMenu.tsx b/src/components/layout/MobileMenu.tsx
index 877cf61a..4251e14b 100644
--- a/src/components/layout/MobileMenu.tsx
+++ b/src/components/layout/MobileMenu.tsx
@@ -6,6 +6,7 @@ import Link from "next/link";
import { useTranslations } from "next-intl";
import { useRef, useState } from "react";
import { flushSync } from "react-dom";
+import { AccountLink } from "@/components/layout/AccountLink";
import { Button } from "@/components/ui/button";
import {
Sheet,
@@ -279,13 +280,13 @@ export function MobileMenu({ rootCategories, basePath }: MobileMenuProps) {
-
{t("myAccount")}
-
+
diff --git a/src/components/order/OrderPlacedSkeleton.tsx b/src/components/order/OrderPlacedSkeleton.tsx
new file mode 100644
index 00000000..ea9eea9d
--- /dev/null
+++ b/src/components/order/OrderPlacedSkeleton.tsx
@@ -0,0 +1,112 @@
+/**
+ * Skeleton mirroring `order-placed/[id]/page.tsx` (2 items scenario):
+ * - Success header (text-center mb-10): check icon (w-16 h-16) + thanks h1 (text-2xl)
+ * + order number (text-base) + email confirmation note (text-sm mt-2)
+ * - Order items card (rounded-xl border mb-6): header (text-lg) + list (divide-y)
+ * + totals footer (border-t)
+ * - Shipping & payment card: 2-col grid with icon/text pairs
+ * - Contact & addresses card: 2-col grid + email footer
+ * - Continue shopping Button (size="lg" h-13)
+ */
+export function OrderPlacedSkeleton(): React.JSX.Element {
+ return (
+