# Pocket: mobile money app

> A bold five-page landing site for a money app: a working app inside a phone frame, live feature demos (freeze a card, round-up calculator, bill splitting, currency conversion), pricing with a yearly switch, security and download.

A shadcn/ui block from the [@ballmac](https://ui.ballmac.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/ballmac/template-pocket).

- Page, with a live preview: https://shadcn.exchange/r/ballmac/template-pocket
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/ballmac/template-pocket-light-90d279731f112f31.png
- Registry item: https://ui.ballmac.com/r/template-pocket.json
- Categories: templates
- Listed: 2026-10-14, source last changed 2026-10-14

## Install

```bash
npx shadcn@latest add https://ui.ballmac.com/r/template-pocket.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`
- Registry items: `utils`, `https://ui.ballmac.com/r/phone-frame.json`, `https://ui.ballmac.com/r/switch.json`, `https://ui.ballmac.com/r/slider.json`

## Notes from the registry

Pages are at /pocket, /pocket/features, /pocket/pricing, /pocket/security and /pocket/download. Plans, comparison rows, FAQ and transactions live in pocket-data.ts. PocketApp (in pocket-theme.tsx) is the working app inside the phone; replace its content with your own screens. The palette is pocketCss.

## Files

### `registry/ballmac/components/templates/pocket/pocket-fonts.ts`

```ts
// Ballmac UI: Pocket template fonts. https://ui.ballmac.com/templates/template-pocket
import { Gabarito } from "next/font/google"

export const pocketSans = Gabarito({ variable: "--pocket-sans", subsets: ["latin"], display: "swap", preload: false })
```

### `registry/ballmac/components/templates/pocket/pocket-data.ts`

```ts
// Ballmac UI: Pocket template data. https://ui.ballmac.com/templates/template-pocket
export const transactions = [
  { name: "Corner Café", detail: "Today, 8:12", amount: -4.8, tone: 1, emoji: "☕" },
  { name: "From Sam", detail: "Yesterday", amount: 120, tone: 0, emoji: "↓" },
  { name: "City Transit", detail: "Yesterday", amount: -2.75, tone: 3, emoji: "🚆" },
  { name: "Market Hall", detail: "Monday", amount: -38.12, tone: 2, emoji: "🥬" },
  { name: "Pilates Studio", detail: "Sunday", amount: -22, tone: 4, emoji: "🧘" },
]

export type Plan = { id: string; name: string; monthly: number; annual: number; blurb: string; features: string[]; featured?: boolean }
export const plans: Plan[] = [
  { id: "free", name: "Free", monthly: 0, annual: 0, blurb: "Everything you need to stop using a spreadsheet.", features: ["Free virtual card", "Instant transfers to friends", "Round-ups to one pot", "Spending insights"] },
  { id: "plus", name: "Plus", monthly: 6, annual: 5, blurb: "For people who travel, save and split things.", features: ["Everything in Free", "Fee-free spending in 40 currencies", "Unlimited savings pots", "Bill splitting with reminders", "Priority chat support"], featured: true },
  { id: "metal", name: "Metal", monthly: 16, annual: 13, blurb: "A heavy card and a lot of perks.", features: ["Everything in Plus", "Metal card, engraved", "Airport lounge passes", "Travel and phone insurance", "Cashback on every purchase"] },
]

export const compare = [
  ["Virtual card", true, true, true],
  ["Physical card", "$5", true, true],
  ["Savings pots", "1", "Unlimited", "Unlimited"],
  ["Foreign spending fee", "1.5%", "None", "None"],
  ["ATM withdrawals a month", "$200", "$800", "Unlimited"],
  ["Bill splitting", false, true, true],
  ["Cashback", false, false, "1%"],
  ["Support", "Chat", "Priority chat", "24/7 phone"],
] as const

export const faqs = [
  { q: "Is Pocket a bank?", a: "Pocket is a money app. Accounts are held at Harbor Bank, N.A., Member FDIC, and your deposits are insured up to $250,000." },
  { q: "How do round-ups work?", a: "Every card purchase is rounded up to the next dollar and the difference moves to your pot. Spend $4.20 and $0.80 is saved." },
  { q: "Are there hidden fees?", a: "No. The Free plan has no monthly fee, no overdraft fee and no minimum balance. Paid plans show their price on this page and nowhere else." },
  { q: "What if I lose my phone?", a: "Sign in on another device, freeze the card in one tap and revoke the old phone. Nothing is stored on the device." },
  { q: "Which countries does it work in?", a: "The card works anywhere Visa does. Sending money to friends is available in 31 countries today." },
  { q: "Can I close my account?", a: "Yes, any time, in the app. Your balance goes to the bank account you choose within one working day." },
]

export const currencies = [["USD", 1, "$"], ["EUR", 0.92, "€"], ["GBP", 0.79, "£"], ["JPY", 156.4, "¥"], ["MXN", 17.1, "MX$"]] as const

export const money = (n: number, digits = 2) => `${n < 0 ? "−" : ""}$${Math.abs(n).toLocaleString("en-US", { minimumFractionDigits: digits, maximumFractionDigits: digits })}`
```

### `registry/ballmac/components/templates/pocket/pocket-theme.tsx`

```tsx
// Ballmac UI: Pocket template shell. https://ui.ballmac.com/templates/template-pocket
"use client"

import * as React from "react"
import { Apple, Bell, CreditCard, Home as HomeIcon, Menu, PiggyBank, Play, QrCode, Send, X } from "lucide-react"

import { PhoneFrame } from "@/components/ballmac/phone-frame"
import { Switch } from "@/components/ballmac/switch"
import { money, transactions } from "@/components/ballmac/templates/pocket/pocket-data"
import { pocketSans } from "@/components/ballmac/templates/pocket/pocket-fonts"
import { cn } from "@/lib/utils"

type PocketPage = "home" | "features" | "pricing" | "security" | "download"
type PocketHrefs = Record<PocketPage, string>

const defaultHrefs: PocketHrefs = { home: "/pocket", features: "/pocket/features", pricing: "/pocket/pricing", security: "/pocket/security", download: "/pocket/download" }

/** Pocket's palette: mint paper, navy ink, cobalt and one loud lime. Dark mode is midnight with the lime turned up. */
const pocketCss = `
.pocket-theme,body:not(:has([data-gallery])):has(.pocket-theme){--background:oklch(0.985 0.012 165);--foreground:oklch(0.2 0.06 265);--card:oklch(1 0 0);--card-foreground:oklch(0.2 0.06 265);--popover:oklch(1 0 0);--popover-foreground:oklch(0.2 0.06 265);--primary:oklch(0.47 0.22 267);--primary-foreground:oklch(0.99 0.005 165);--secondary:oklch(0.95 0.025 165);--secondary-foreground:oklch(0.2 0.06 265);--muted:oklch(0.95 0.02 165);--muted-foreground:oklch(0.45 0.05 265);--accent:oklch(0.93 0.04 150);--accent-foreground:oklch(0.2 0.06 265);--border:oklch(0.2 0.06 265 / 12%);--input:oklch(0.2 0.06 265 / 20%);--ring:oklch(0.55 0.22 267);--surface:oklch(0.965 0.02 165);--destructive:oklch(0.52 0.21 27);--chart-1:oklch(0.9 0.2 125);--chart-2:oklch(0.72 0.17 30);--chart-3:oklch(0.62 0.2 300);--chart-4:oklch(0.78 0.13 200);--chart-5:oklch(0.85 0.14 85);--pocket-ink:oklch(0.2 0.06 265);--pocket-on-lime:oklch(0.2 0.06 265);--pocket-navy:oklch(0.2 0.07 265);--pocket-on-navy:oklch(0.98 0.01 165);--radius:1.5rem}
.dark .pocket-theme,.dark body:not(:has([data-gallery])):has(.pocket-theme){--background:oklch(0.16 0.045 265);--foreground:oklch(0.96 0.015 165);--card:oklch(0.21 0.05 265);--card-foreground:oklch(0.96 0.015 165);--popover:oklch(0.23 0.05 265);--popover-foreground:oklch(0.96 0.015 165);--primary:oklch(0.9 0.2 125);--primary-foreground:oklch(0.2 0.06 265);--secondary:oklch(0.26 0.05 265);--secondary-foreground:oklch(0.96 0.015 165);--muted:oklch(0.25 0.05 265);--muted-foreground:oklch(0.76 0.04 250);--accent:oklch(0.3 0.06 265);--accent-foreground:oklch(0.96 0.015 165);--border:oklch(1 0 0 / 11%);--input:oklch(1 0 0 / 16%);--ring:oklch(0.9 0.2 125);--surface:oklch(0.19 0.047 265);--destructive:oklch(0.7 0.19 27);--chart-1:oklch(0.9 0.2 125);--chart-2:oklch(0.76 0.15 30);--chart-3:oklch(0.74 0.17 300);--chart-4:oklch(0.8 0.12 200);--chart-5:oklch(0.86 0.13 85);--pocket-navy:oklch(0.12 0.045 265)}
body:not(:has([data-gallery])):has(.pocket-theme){font-family:var(--pocket-sans),ui-sans-serif,system-ui,sans-serif}
@keyframes pocket-bob{0%,100%{transform:translateY(0) rotate(var(--r,0deg))}50%{transform:translateY(-8px) rotate(var(--r,0deg))}}
.pocket-bob{animation:pocket-bob 5s ease-in-out infinite;animation-play-state:var(--bm-ambient-state,running)}
@media (prefers-reduced-motion:reduce){.pocket-bob{animation:none}}
`

const display = "font-black tracking-[-0.035em]"
const onLime = "text-[var(--pocket-on-lime)]"
const txTone = ["bg-chart-1", "bg-chart-5", "bg-chart-4", "bg-chart-2", "bg-chart-3"]

/** The Pocket app inside a phone: balance, quick actions and three tabs (Home, Card, Save). Tap around. */
function PocketApp({ className, defaultTab = "home" }: { className?: string; defaultTab?: "home" | "card" | "save" }) {
  const [tab, setTab] = React.useState<"home" | "card" | "save">(defaultTab)
  const [frozen, setFrozen] = React.useState(false)
  const id = React.useId()
  const tabs = [["home", "Home", HomeIcon], ["card", "Card", CreditCard], ["save", "Save", PiggyBank]] as const
  return (
    <PhoneFrame screenWidth={390} className={cn("w-[min(100%,290px)]", className)} screenClassName="pocket-theme bg-background text-foreground">
      <div className="flex h-full flex-col text-[15px]" style={{ fontFamily: "var(--pocket-sans), ui-sans-serif, system-ui, sans-serif" }}>
        <div className="flex items-center justify-between px-5 pt-2">
          <div className="flex items-center gap-3"><span aria-hidden="true" className="bg-chart-3 flex size-10 items-center justify-center rounded-full font-black text-white">M</span><div><p className="text-muted-foreground text-xs">Good morning</p><p className="font-extrabold">Maya</p></div></div>
          <span aria-hidden="true" className="bg-secondary flex size-10 items-center justify-center rounded-full"><Bell className="size-5" /></span>
        </div>
        <div role="tabpanel" id={`${id}-panel`} aria-labelledby={`${id}-${tab}`} className="min-h-0 flex-1 overflow-hidden px-5 pt-4">
          {tab === "home" && (
            <>
              <div className="bg-primary text-primary-foreground rounded-3xl p-5">
                <p className="text-sm font-semibold">Total balance</p>
                <p className={cn("mt-1 text-[40px] leading-none tabular-nums", display)}>$12,480<span className="text-2xl opacity-100">.62</span></p>
                <p className="bg-card text-card-foreground mt-3 inline-block rounded-full px-3 py-1 text-xs font-extrabold">+$212.40 this week</p>
              </div>
              <div className="mt-4 grid grid-cols-4 gap-2 text-center text-xs font-bold">{[["Send", Send], ["Request", Apple], ["Top up", QrCode], ["More", Play]].map(([l, Icon]) => { const I = Icon as typeof Send; return <div key={l as string}><span aria-hidden="true" className="bg-secondary mx-auto flex size-12 items-center justify-center rounded-2xl"><I className="size-5" /></span><span className="mt-1 block">{l as string}</span></div> })}</div>
              <p className="mt-4 text-sm font-extrabold">Recent</p>
              <ul className="mt-2 grid gap-2.5">{transactions.slice(0, 4).map((t) => <li key={t.name} className="flex items-center gap-3"><span aria-hidden="true" className={cn("flex size-10 items-center justify-center rounded-full text-base text-[var(--pocket-on-lime)]", txTone[t.tone])}>{t.emoji}</span><span className="min-w-0 flex-1"><span className="block truncate font-bold">{t.name}</span><span className="text-muted-foreground block text-xs">{t.detail}</span></span><span className={cn("font-extrabold tabular-nums", t.amount > 0 && "text-primary")}>{t.amount > 0 ? "+" : ""}{money(t.amount)}</span></li>)}</ul>
            </>
          )}
          {tab === "card" && (
            <>
              <div className={cn("relative aspect-[1.6] overflow-hidden rounded-3xl p-5 text-[var(--pocket-on-navy)] transition-opacity motion-reduce:transition-none", "bg-[var(--pocket-navy)]", frozen && "opacity-50")}>
                <div aria-hidden="true" className="bg-chart-1 absolute -end-10 -bottom-10 aspect-square w-40 rounded-full" /><div aria-hidden="true" className="bg-chart-3 absolute -end-2 -bottom-16 aspect-square w-32 rounded-full" />
                <p className={cn("relative text-xl", display)}>pocket</p><p className="relative mt-8 text-lg font-bold tracking-widest tabular-nums">•••• 4821</p><p className="relative mt-1 text-xs">MAYA OKAFOR · 09/29</p>
                {frozen && <span className="bg-chart-4 absolute top-4 end-4 rounded-full px-3 py-1 text-xs font-extrabold text-[var(--pocket-on-lime)]">Frozen</span>}
              </div>
              <div className="bg-secondary mt-4 flex items-center justify-between rounded-2xl p-4"><span><span className="block font-extrabold">Freeze card</span><span className="text-muted-foreground text-xs">Stops every payment instantly</span></span><Switch checked={frozen} onCheckedChange={setFrozen} aria-label="Freeze card" /></div>
              <dl className="mt-3 grid gap-2 text-sm">{[["Daily limit", "$2,000"], ["Online payments", "On"], ["Contactless", "On"]].map(([k, v]) => <div key={k} className="bg-card flex justify-between rounded-xl border px-4 py-3"><dt className="text-muted-foreground">{k}</dt><dd className="font-extrabold">{v}</dd></div>)}</dl>
            </>
          )}
          {tab === "save" && (
            <>
              <div className="bg-chart-1 rounded-3xl p-5 text-[var(--pocket-on-lime)]"><p className="text-sm font-bold">Holiday fund</p><p className={cn("mt-1 text-4xl tabular-nums", display)}>$1,240</p><div className="mt-3 h-3 overflow-hidden rounded-full bg-black/15" role="progressbar" aria-label="Holiday fund progress" aria-valuemin={0} aria-valuemax={100} aria-valuenow={62}><div className="h-full w-[62%] rounded-full bg-[var(--pocket-ink)]" /></div><p className="mt-2 text-xs font-bold">62% of $2,000 · Lisbon, June</p></div>
              <p className="mt-4 text-sm font-extrabold">Round-ups this month</p>
              <p className={cn("text-3xl tabular-nums", display)}>$37.20</p>
              <ul className="mt-3 grid gap-2">{[["Corner Café", "+$0.20"], ["City Transit", "+$0.25"], ["Market Hall", "+$0.88"]].map(([n, a]) => <li key={n} className="bg-card flex justify-between rounded-xl border px-4 py-3"><span className="font-bold">{n}</span><span className="text-primary font-extrabold tabular-nums">{a}</span></li>)}</ul>
            </>
          )}
        </div>
        <div role="tablist" aria-label="App sections" className="bg-card mx-4 mb-7 mt-2 grid grid-cols-3 rounded-full border p-1">
          {tabs.map(([k, label, Icon]) => <button key={k} type="button" role="tab" id={`${id}-${k}`} aria-selected={tab === k} aria-controls={`${id}-panel`} onClick={() => setTab(k)} className="aria-selected:bg-primary aria-selected:text-primary-foreground focus-visible:ring-ring/50 flex h-10 items-center justify-center gap-1.5 rounded-full text-sm font-extrabold outline-none focus-visible:ring-2"><Icon className="size-4" aria-hidden="true" />{label}</button>)}
        </div>
      </div>
    </PhoneFrame>
  )
}

/** App Store and Google Play buttons that go to the download page. */
function StoreButtons({ href, className }: { href: string; className?: string }) {
  const b = "bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)] focus-visible:ring-ring inline-flex h-14 items-center gap-3 rounded-2xl px-5 outline-none transition-transform hover:translate-y-[var(--bm-lift,-2px)] focus-visible:ring-[3px] motion-reduce:transition-none motion-reduce:hover:translate-y-0"
  return (
    <div className={cn("flex flex-wrap gap-3", className)}>
      <a href={href} className={b}><Apple className="size-7" aria-hidden="true" /><span className="text-start leading-tight"><span className="block text-[11px] font-medium">Download on the</span><span className="block text-lg font-extrabold">App Store</span></span></a>
      <a href={href} className={b}><Play className="size-7" aria-hidden="true" /><span className="text-start leading-tight"><span className="block text-[11px] font-medium">Get it on</span><span className="block text-lg font-extrabold">Google Play</span></span></a>
    </div>
  )
}

const links: { key: PocketPage; label: string }[] = [{ key: "features", label: "Features" }, { key: "pricing", label: "Pricing" }, { key: "security", label: "Security" }]

type PocketShellProps = React.ComponentProps<"div"> & {
  /** The page being shown, so its nav link is marked current. */
  page: PocketPage
  /** Override where pages live (used by previews). */
  hrefs?: Partial<PocketHrefs>
}

/** Pocket's frame: a floating pill header, and a navy footer with a giant wordmark. */
function PocketShell({ page, hrefs: overrides, className, style, children, ...props }: PocketShellProps) {
  const hrefs = { ...defaultHrefs, ...overrides }
  const [open, setOpen] = React.useState(false)
  React.useEffect(() => {
    const classes = [pocketSans.variable].filter(Boolean)
    document.body.classList.add(...classes)
    return () => document.body.classList.remove(...classes)
  }, [])
  return (
    <div
      data-slot="pocket"
      className={cn("pocket-theme bg-background text-foreground relative min-h-dvh overflow-x-clip", pocketSans.variable, className)}
      style={{ fontFamily: "var(--pocket-sans), ui-sans-serif, system-ui, sans-serif", ...style }}
      {...props}
    >
      <style>{pocketCss}</style>
      <header className="sticky top-3 z-40 px-3 sm:px-6">
        <div className="bg-card/90 mx-auto flex h-16 max-w-6xl items-center justify-between rounded-full border pe-2 ps-5 shadow-sm backdrop-blur-xl">
          <a href={hrefs.home} className={cn("focus-visible:ring-ring/50 flex items-center gap-2 rounded-full text-2xl outline-none focus-visible:ring-[3px]", display)}><span aria-hidden="true" className="bg-primary text-primary-foreground flex size-8 items-center justify-center rounded-xl text-lg">p</span>pocket</a>
          <nav aria-label="Main" className="hidden items-center gap-1 md:flex">{links.map((l) => <a key={l.key} href={hrefs[l.key]} aria-current={page === l.key ? "page" : undefined} className="hover:bg-accent aria-[current=page]:bg-accent focus-visible:ring-ring/50 rounded-full px-4 py-2 text-sm font-extrabold outline-none transition-colors focus-visible:ring-[3px] motion-reduce:transition-none">{l.label}</a>)}</nav>
          <div className="flex items-center gap-1">
            <a href={hrefs.download} className="bg-primary text-primary-foreground focus-visible:ring-ring/50 inline-flex h-11 items-center rounded-full px-5 text-sm font-extrabold outline-none transition-transform hover:scale-[1.03] focus-visible:ring-[3px] motion-reduce:transition-none motion-reduce:hover:scale-100">Get the app</a>
            <button type="button" aria-label={open ? "Close menu" : "Open menu"} aria-expanded={open} aria-controls="pocket-mobile-menu" onClick={() => setOpen((v) => !v)} className="hover:bg-accent focus-visible:ring-ring/50 inline-flex size-11 items-center justify-center rounded-full outline-none focus-visible:ring-[3px] md:hidden">{open ? <X className="size-5" aria-hidden="true" /> : <Menu className="size-5" aria-hidden="true" />}</button>
          </div>
        </div>
        {open && <nav id="pocket-mobile-menu" aria-label="Mobile" className="bg-card mx-auto mt-2 max-w-6xl rounded-3xl border p-2 md:hidden">{links.map((l) => <a key={l.key} href={hrefs[l.key]} className="hover:bg-accent block rounded-2xl px-4 py-3 text-lg font-extrabold">{l.label}</a>)}</nav>}
      </header>
      {children}
      <footer className="mt-24 overflow-hidden bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)]">
        <div className="mx-auto grid max-w-6xl gap-10 px-4 pt-16 pb-6 sm:px-6 md:grid-cols-[1.4fr_1fr_1fr_1fr]">
          <div><p className="max-w-xs text-xl font-bold text-pretty">Money that keeps up with you.</p><StoreButtons href={hrefs.download} className="mt-6 [&>a]:bg-white/10" /></div>
          {[["Product", [["Features", hrefs.features], ["Pricing", hrefs.pricing], ["Download", hrefs.download]]], ["Trust", [["Security", hrefs.security], ["Status", hrefs.security], ["Bug bounty", hrefs.security]]], ["Company", [["About", hrefs.home], ["Careers", hrefs.home], ["Press", hrefs.home]]]].map(([t, items]) => <div key={t as string}><h2 className="text-xs font-extrabold tracking-[0.14em] uppercase">{t as string}</h2><ul className="mt-4 grid gap-2.5">{(items as string[][]).map(([l, h]) => <li key={l}><a href={h} className="hover:underline">{l}</a></li>)}</ul></div>)}
        </div>
        <p aria-hidden="true" className={cn("text-chart-1 -mb-[0.18em] select-none text-center text-[clamp(6rem,26vw,22rem)] leading-none", display)}>pocket</p>
        <p className="mx-auto max-w-6xl px-4 pb-6 text-xs sm:px-6">Pocket is a financial technology company, not a bank. Banking services by Harbor Bank, N.A., Member FDIC. © 2026 Pocket Labs.</p>
      </footer>
    </div>
  )
}

export { PocketApp, PocketShell, StoreButtons, defaultHrefs as pocketDefaultHrefs, display as pocketDisplayClass, onLime as pocketOnLime, type PocketHrefs, type PocketPage, type PocketShellProps }
```

### `registry/ballmac/components/templates/pocket/pocket-home.tsx`

```tsx
// Ballmac UI: Pocket home page. https://ui.ballmac.com/templates/template-pocket
"use client"

import * as React from "react"
import { ArrowRight, Globe2, PiggyBank, ShieldCheck, Snowflake, Users } from "lucide-react"

import { PocketApp, PocketShell, StoreButtons, pocketDisplayClass, type PocketHrefs } from "@/components/ballmac/templates/pocket/pocket-theme"
import { cn } from "@/lib/utils"

const cards = [
  { icon: PiggyBank, title: "Round-ups that add up", body: "Every purchase rounds up to the next dollar and the change lands in a pot. Most people save $40 a month without noticing.", tone: "bg-chart-1" },
  { icon: Snowflake, title: "Freeze it in one tap", body: "Lost your card? Tap once and every payment stops. Tap again and you are back.", tone: "bg-chart-4" },
  { icon: Globe2, title: "Spend anywhere", body: "Pay in 40 currencies at the real exchange rate with no fee. The rate you see is the rate you get.", tone: "bg-chart-5" },
  { icon: Users, title: "Split without the awkward", body: "Send a request for your share of dinner, with a gentle reminder so you do not have to be the one who asks.", tone: "bg-chart-2" },
]
const reviews = [
  ["It’s the first money app I open on purpose.", "Priya N.", "App Store"],
  ["Round-ups paid for our entire holiday. I did nothing.", "Tom & Lucia", "Google Play"],
  ["Froze my card from a taxi in Lisbon. Unfroze it at the hotel.", "Dev R.", "App Store"],
]

type PocketHomeProps = React.ComponentProps<"div"> & { hrefs?: Partial<PocketHrefs> }

/** The Pocket home page: a hero with a working app in a phone, four feature blocks, proof and the download buttons. */
function PocketHome({ hrefs, ...props }: PocketHomeProps) {
  const link = { features: "/pocket/features", pricing: "/pocket/pricing", download: "/pocket/download", security: "/pocket/security", ...hrefs }
  return (
    <PocketShell page="home" hrefs={hrefs} {...props}>
      <main>
        <section aria-labelledby="ph-title" className="relative isolate mx-auto grid max-w-6xl items-center gap-12 px-4 pt-14 pb-20 sm:px-6 lg:grid-cols-[1.15fr_1fr] lg:pt-24">
          <div aria-hidden="true" className="bg-chart-1/50 absolute top-10 end-0 -z-10 aspect-square w-[min(80vw,34rem)] rounded-full blur-3xl" />
          <div>
            <p className="bg-card inline-flex items-center gap-2 rounded-full border px-4 py-1.5 text-sm font-extrabold"><span className="bg-chart-1 size-2.5 rounded-full" aria-hidden="true" />2.4 million pockets and counting</p>
            <h1 id="ph-title" className={cn("mt-6 text-[clamp(3.4rem,10vw,8rem)] leading-[0.88] text-balance", pocketDisplayClass)}>Money that <span className="bg-chart-1 inline-block -rotate-2 rounded-2xl px-3 text-[var(--pocket-on-lime)]">keeps up.</span></h1>
            <p className="text-muted-foreground mt-6 max-w-lg text-xl font-medium text-pretty">One app for spending, saving and splitting. No fees to open, no fees to leave, and a card you can freeze from the back of a taxi.</p>
            <StoreButtons href={link.download} className="mt-8" />
            <p className="text-muted-foreground mt-4 flex items-center gap-2 text-sm font-semibold"><ShieldCheck className="size-4" aria-hidden="true" />FDIC insured up to $250,000 · Rated 4.8 by 61,000 people</p>
          </div>
          <div className="relative mx-auto w-full max-w-sm">
            <PocketApp className="mx-auto w-[min(100%,300px)]" />
            <p aria-hidden="true" className="bg-chart-1 pocket-bob absolute top-16 -start-2 rounded-2xl px-4 py-2 text-sm font-extrabold text-[var(--pocket-on-lime)] shadow-lg [--r:-6deg] sm:-start-10" style={{ transform: "rotate(-6deg)" }}>+$0.20 saved</p>
            <p aria-hidden="true" className="bg-card pocket-bob absolute end-0 bottom-28 flex items-center gap-2 rounded-2xl border px-4 py-2 text-sm font-extrabold shadow-lg [--r:5deg] sm:-end-8" style={{ transform: "rotate(5deg)", animationDelay: "1.2s" }}><Snowflake className="text-primary size-4" />Card frozen</p>
          </div>
        </section>

        <section aria-label="Featured in" className="border-y">
          <div className="mx-auto flex max-w-6xl flex-wrap items-center justify-center gap-x-12 gap-y-3 px-4 py-6 sm:px-6"><span className="text-muted-foreground text-xs font-extrabold tracking-[0.14em] uppercase">As seen in</span>{["The Daily Ledger", "Fast Money", "Wired Weekly", "Product Hunt"].map((n) => <span key={n} className={cn("text-muted-foreground text-xl", pocketDisplayClass)}>{n}</span>)}</div>
        </section>

        <section aria-labelledby="ph-feat" className="mx-auto max-w-6xl px-4 py-20 sm:px-6">
          <h2 id="ph-feat" className={cn("max-w-2xl text-[clamp(2.4rem,6vw,4.5rem)] leading-[0.95] text-balance", pocketDisplayClass)}>Everything your money app should have done years ago.</h2>
          <ul className="mt-12 grid gap-4 md:grid-cols-2">{cards.map((c) => <li key={c.title} className={cn("rounded-[2rem] p-8 text-[var(--pocket-on-lime)] sm:p-10", c.tone)}><c.icon className="size-9" aria-hidden="true" /><h3 className={cn("mt-10 text-3xl", pocketDisplayClass)}>{c.title}</h3><p className="mt-3 max-w-md text-lg font-medium text-pretty">{c.body}</p></li>)}</ul>
          <a href={link.features} className="bg-primary text-primary-foreground focus-visible:ring-ring/50 mt-8 inline-flex h-14 items-center gap-2 rounded-full px-8 text-lg font-extrabold outline-none focus-visible:ring-[3px]">See every feature <ArrowRight className="size-5 rtl:rotate-180" aria-hidden="true" /></a>
        </section>

        <section aria-label="Pocket in numbers" className="bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)]">
          <ul className="mx-auto grid max-w-6xl gap-8 px-4 py-16 sm:grid-cols-3 sm:px-6">{[["$0", "to open, hold or close an account"], ["40", "currencies at the real rate"], ["11 min", "average wait for a human reply"]].map(([n, l]) => <li key={l}><span className={cn("text-chart-1 block text-[clamp(3.5rem,8vw,6rem)] leading-none", pocketDisplayClass)}>{n}</span><span className="mt-2 block text-lg font-medium">{l}</span></li>)}</ul>
        </section>

        <section aria-labelledby="ph-rev" className="mx-auto max-w-6xl px-4 py-20 sm:px-6">
          <h2 id="ph-rev" className={cn("text-[clamp(2.4rem,6vw,4rem)] leading-none", pocketDisplayClass)}>People say nice things</h2>
          <ul className="mt-10 grid gap-4 md:grid-cols-3">{reviews.map(([q, n, s], i) => <li key={n} className={cn("bg-card rounded-[2rem] border p-8", i === 1 && "md:translate-y-6")}><p className="text-2xl leading-snug font-extrabold text-balance">“{q}”</p><p className="text-muted-foreground mt-6 text-sm font-bold">{n} · {s}</p></li>)}</ul>
        </section>

        <section aria-labelledby="ph-cta" className="mx-auto max-w-6xl px-4 pb-8 sm:px-6">
          <div className="bg-primary text-primary-foreground rounded-[2.5rem] px-6 py-16 text-center sm:px-14">
            <h2 id="ph-cta" className={cn("mx-auto max-w-2xl text-[clamp(2.4rem,6vw,4.5rem)] leading-[0.95] text-balance", pocketDisplayClass)}>Open an account in about four minutes.</h2>
            <p className="mx-auto mt-4 max-w-md text-lg font-medium text-pretty">All you need is your phone and a photo ID. We will do the rest.</p>
            <div className="mt-8 flex justify-center"><a href={link.download} className="bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)] focus-visible:ring-ring inline-flex h-14 items-center gap-2 rounded-full px-8 text-lg font-extrabold outline-none focus-visible:ring-[3px]">Get Pocket <ArrowRight className="size-5 rtl:rotate-180" aria-hidden="true" /></a></div>
          </div>
        </section>
      </main>
    </PocketShell>
  )
}

export { PocketHome, type PocketHomeProps }
```

### `registry/ballmac/components/templates/pocket/pocket-features.tsx`

```tsx
// Ballmac UI: Pocket features page. https://ui.ballmac.com/templates/template-pocket
"use client"

import * as React from "react"
import { Send, Snowflake } from "lucide-react"

import { Slider } from "@/components/ballmac/slider"
import { Switch } from "@/components/ballmac/switch"
import { currencies, money } from "@/components/ballmac/templates/pocket/pocket-data"
import { PocketShell, pocketDisplayClass, type PocketHrefs } from "@/components/ballmac/templates/pocket/pocket-theme"
import { cn } from "@/lib/utils"

const bars = [["Food", 340, "bg-chart-1"], ["Travel", 215, "bg-chart-4"], ["Fun", 180, "bg-chart-5"], ["Home", 120, "bg-chart-2"]] as const
const people = [["Sam", "bg-chart-1", true], ["Ana", "bg-chart-4", true], ["Joe", "bg-chart-5", false], ["Mei", "bg-chart-2", false]] as const

type PocketFeaturesProps = React.ComponentProps<"div"> & { hrefs?: Partial<PocketHrefs> }

/** The features page: five live demos instead of five screenshots. Freeze a card, tune round-ups, split a bill, convert money. */
function PocketFeatures({ hrefs, ...props }: PocketFeaturesProps) {
  const [frozen, setFrozen] = React.useState(false)
  const [spend, setSpend] = React.useState(900)
  const [paid, setPaid] = React.useState<string[]>(["Sam", "Ana"])
  const [amount, setAmount] = React.useState("100")
  const [cur, setCur] = React.useState<(typeof currencies)[number][0]>("EUR")
  const savedPerMonth = Math.round(spend * 0.045)
  const rate = currencies.find((c) => c[0] === cur)!
  const converted = (Number(amount) || 0) * rate[1]
  const bill = 128
  const share = bill / people.length
  const total = bars.reduce((n, b) => n + b[1], 0)
  const card = "rounded-[2rem] border p-8 sm:p-10"
  return (
    <PocketShell page="features" hrefs={hrefs} {...props}>
      <main className="mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20">
        <h1 className={cn("max-w-3xl text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance", pocketDisplayClass)}>Try it right here.</h1>
        <p className="text-muted-foreground mt-5 max-w-xl text-xl font-medium text-pretty">Everything below works. Freeze the card, drag the slider, split the bill.</p>

        <div className="mt-14 grid gap-4 lg:grid-cols-6">
          <section aria-labelledby="pf-card" className={cn(card, "bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)] lg:col-span-3")}>
            <h2 id="pf-card" className={cn("text-3xl", pocketDisplayClass)}>Freeze it in one tap</h2>
            <p className="mt-2 max-w-sm font-medium text-pretty">Lost it? Misplaced it? Stop every payment instantly, then undo it when you find it in a coat.</p>
            <div className={cn("relative mt-8 aspect-[1.6] max-w-sm overflow-hidden rounded-3xl bg-primary p-6 text-primary-foreground transition-all duration-500 motion-reduce:transition-none", frozen && "scale-[0.97] opacity-60 saturate-0")}>
              <p className={cn("text-2xl", pocketDisplayClass)}>pocket</p><p className="mt-12 text-xl font-bold tracking-widest tabular-nums">•••• •••• •••• 4821</p>
              {frozen && <span className="bg-card text-card-foreground absolute top-5 end-5 flex items-center gap-1.5 rounded-full px-3 py-1 text-sm font-extrabold"><Snowflake className="size-4" aria-hidden="true" />Frozen</span>}
            </div>
            <label className="mt-6 flex max-w-sm cursor-pointer items-center justify-between gap-4 rounded-2xl bg-white/10 p-4"><span className="font-extrabold">Freeze card</span><Switch checked={frozen} onCheckedChange={setFrozen} /></label>
            <p role="status" className="mt-3 text-sm font-semibold">{frozen ? "Payments are off. Nothing can be charged." : "Your card is live."}</p>
          </section>

          <section aria-labelledby="pf-round" className={cn(card, "bg-chart-1 text-[var(--pocket-on-lime)] lg:col-span-3")}>
            <h2 id="pf-round" className={cn("text-3xl", pocketDisplayClass)}>Round-ups, calculated</h2>
            <p className="mt-2 max-w-sm font-medium text-pretty">Tell us roughly what you spend on your card each month.</p>
            <p id="pf-spend" className="mt-8 flex items-baseline justify-between font-extrabold"><span>Monthly card spending</span><span className="text-2xl tabular-nums">{money(spend, 0)}</span></p>
            <Slider aria-labelledby="pf-spend" thumbLabels={["Monthly spending"]} min={200} max={3000} step={50} value={[spend]} onValueChange={(v) => setSpend(v[0]!)} className="mt-4 [&_[data-slot=slider-track]]:bg-black/20 [&_[data-slot=slider-range]]:bg-[var(--pocket-ink)] [&_[data-slot=slider-thumb]]:border-[var(--pocket-ink)] [&_[data-slot=slider-thumb]]:bg-white" />
            <div className="mt-10"><p className="font-extrabold">You would save about</p><p className={cn("text-[clamp(3.5rem,8vw,6rem)] leading-none tabular-nums", pocketDisplayClass)}><output aria-live="polite">{money(savedPerMonth, 0)}</output></p><p className="mt-1 font-bold">a month · {money(savedPerMonth * 12, 0)} a year</p></div>
          </section>

          <section aria-labelledby="pf-ins" className={cn(card, "bg-card lg:col-span-2")}>
            <h2 id="pf-ins" className={cn("text-3xl", pocketDisplayClass)}>Where it went</h2>
            <p className="text-muted-foreground mt-2 text-lg font-medium">{money(total, 0)} in August</p>
            <ul className="mt-6 grid gap-4">{bars.map(([n, v, c]) => <li key={n}><div className="flex justify-between text-sm font-extrabold"><span>{n}</span><span className="tabular-nums">{money(v, 0)}</span></div><div className="bg-muted mt-1.5 h-4 overflow-hidden rounded-full" aria-hidden="true"><div className={cn("h-full rounded-full", c)} style={{ width: `${(v / 340) * 100}%` }} /></div></li>)}</ul>
          </section>

          <section aria-labelledby="pf-split" className={cn(card, "bg-card lg:col-span-2")}>
            <h2 id="pf-split" className={cn("text-3xl", pocketDisplayClass)}>Split the bill</h2>
            <p className="text-muted-foreground mt-2 font-medium">Dinner, {money(bill, 0)} · {money(share, 0)} each</p>
            <ul className="mt-5 grid gap-2">{people.map(([n, c]) => { const isPaid = paid.includes(n); return <li key={n} className="flex items-center justify-between gap-3"><span className="flex items-center gap-3"><span aria-hidden="true" className={cn("flex size-10 items-center justify-center rounded-full font-black text-[var(--pocket-on-lime)]", c)}>{n[0]}</span><span className="font-bold">{n}</span></span>{isPaid ? <span className="bg-secondary rounded-full px-3 py-1 text-sm font-extrabold">Paid</span> : <button type="button" onClick={() => setPaid((p) => [...p, n])} className="bg-primary text-primary-foreground focus-visible:ring-ring/50 inline-flex h-9 items-center gap-1.5 rounded-full px-4 text-sm font-extrabold outline-none focus-visible:ring-[3px]"><Send className="size-3.5 rtl:-scale-x-100" aria-hidden="true" />Remind {n}</button>}</li> })}</ul>
            <p role="status" className="text-muted-foreground mt-4 text-sm font-semibold">{paid.length === people.length ? "Everyone has paid." : `${people.length - paid.length} still to pay.`}</p>
          </section>

          <section aria-labelledby="pf-fx" className={cn(card, "bg-chart-4 text-[var(--pocket-on-lime)] lg:col-span-2")}>
            <h2 id="pf-fx" className={cn("text-3xl", pocketDisplayClass)}>Real exchange rate</h2>
            <p className="mt-2 font-medium">No fee, no markup.</p>
            <div className="mt-6 grid gap-3">
              <div className="grid gap-1.5"><label htmlFor="pf-amount" className="text-sm font-extrabold">You send (USD)</label><input id="pf-amount" inputMode="decimal" value={amount} onChange={(e) => setAmount(e.target.value.replace(/[^\d.]/g, ""))} className="h-12 rounded-2xl border-2 border-[var(--pocket-ink)] bg-white/60 px-4 text-lg font-extrabold tabular-nums outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--pocket-ink)]/40" /></div>
              <div role="group" aria-label="Currency" className="flex flex-wrap gap-2">{currencies.slice(1).map(([c]) => <button key={c} type="button" aria-pressed={cur === c} onClick={() => setCur(c)} className="aria-pressed:bg-[var(--pocket-ink)] aria-pressed:text-white focus-visible:ring-[var(--pocket-ink)]/50 h-10 rounded-full border-2 border-[var(--pocket-ink)] px-4 text-sm font-extrabold outline-none focus-visible:ring-[3px]">{c}</button>)}</div>
              <p className="mt-2 font-extrabold">They receive</p>
              <p className={cn("text-4xl tabular-nums", pocketDisplayClass)}><output aria-live="polite">{rate[2]}{converted.toLocaleString("en-US", { maximumFractionDigits: cur === "JPY" ? 0 : 2, minimumFractionDigits: cur === "JPY" ? 0 : 2 })}</output></p>
              <p className="text-sm font-bold">1 USD = {rate[1]} {cur}</p>
            </div>
          </section>
        </div>
      </main>
    </PocketShell>
  )
}

export { PocketFeatures, type PocketFeaturesProps }
```

### `registry/ballmac/components/templates/pocket/pocket-pricing.tsx`

```tsx
// Ballmac UI: Pocket pricing page. https://ui.ballmac.com/templates/template-pocket
"use client"

import * as React from "react"
import { Check, Minus } from "lucide-react"

import { compare, faqs, plans } from "@/components/ballmac/templates/pocket/pocket-data"
import { PocketShell, pocketDisplayClass, type PocketHrefs } from "@/components/ballmac/templates/pocket/pocket-theme"
import { cn } from "@/lib/utils"

type PocketPricingProps = React.ComponentProps<"div"> & { hrefs?: Partial<PocketHrefs> }

/** Pricing: a monthly or yearly switch, three plans, a real comparison table and the questions people ask. */
function PocketPricing({ hrefs, ...props }: PocketPricingProps) {
  const link = { download: "/pocket/download", ...hrefs }
  const [yearly, setYearly] = React.useState(true)
  const cell = (v: string | boolean) => (v === true ? <><Check className="mx-auto size-5" aria-hidden="true" /><span className="sr-only">Included</span></> : v === false ? <><Minus className="text-muted-foreground mx-auto size-5" aria-hidden="true" /><span className="sr-only">Not included</span></> : v)
  return (
    <PocketShell page="pricing" hrefs={hrefs} {...props}>
      <main className="mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20">
        <div className="text-center">
          <h1 className={cn("mx-auto max-w-3xl text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance", pocketDisplayClass)}>Pay for perks, not for banking.</h1>
          <p className="text-muted-foreground mx-auto mt-5 max-w-xl text-xl font-medium text-pretty">The Free plan is free forever. Upgrade only when you want the extras.</p>
          <div role="group" aria-label="Billing period" className="bg-secondary mt-8 inline-flex rounded-full p-1">
            {([[false, "Monthly"], [true, "Yearly"]] as const).map(([v, l]) => <button key={l} type="button" aria-pressed={yearly === v} onClick={() => setYearly(v)} className="aria-pressed:bg-primary aria-pressed:text-primary-foreground focus-visible:ring-ring/50 inline-flex h-11 items-center gap-2 rounded-full px-6 text-sm font-extrabold outline-none focus-visible:ring-[3px]">{l}{v && <span className="bg-chart-1 rounded-full px-2 py-0.5 text-[11px] text-[var(--pocket-on-lime)]">Save 20%</span>}</button>)}
          </div>
        </div>

        <ul className="mt-12 grid gap-4 lg:grid-cols-3">
          {plans.map((p) => {
            const price = yearly ? p.annual : p.monthly
            return (
              <li key={p.id} className={cn("relative flex flex-col rounded-[2rem] border p-8", p.featured ? "bg-primary text-primary-foreground border-transparent lg:-my-4 lg:py-12" : "bg-card")}>
                {p.featured && <span className="bg-chart-1 absolute -top-3 start-8 rounded-full px-3 py-1 text-xs font-extrabold text-[var(--pocket-on-lime)]">Most popular</span>}
                <h2 className={cn("text-2xl", pocketDisplayClass)}>{p.name}</h2>
                <p className="mt-1 text-sm font-medium">{p.blurb}</p>
                <p className="mt-6 flex items-baseline gap-1"><span className={cn("text-6xl leading-none tabular-nums", pocketDisplayClass)}>${price}</span><span className="text-sm font-bold">{price === 0 ? "forever" : "a month"}</span></p>
                <p className="mt-1 min-h-5 text-xs font-semibold">{price > 0 && yearly ? `Billed $${price * 12} a year` : price > 0 ? "Billed monthly" : "No card needed"}</p>
                <ul className="mt-6 grid flex-1 gap-3">{p.features.map((f) => <li key={f} className="flex gap-3 text-sm font-semibold"><Check className="mt-0.5 size-4 shrink-0" aria-hidden="true" />{f}</li>)}</ul>
                <a href={link.download} className={cn("focus-visible:ring-ring mt-8 inline-flex h-12 items-center justify-center rounded-full px-6 font-extrabold outline-none focus-visible:ring-[3px]", p.featured ? "bg-card text-card-foreground" : "bg-primary text-primary-foreground")}>{p.monthly === 0 ? "Get Pocket Free" : `Try ${p.name} free for 30 days`}</a>
              </li>
            )
          })}
        </ul>

        <section aria-labelledby="pp-compare" className="mt-24">
          <h2 id="pp-compare" className={cn("text-[clamp(2rem,5vw,3.5rem)] leading-none", pocketDisplayClass)}>Compare plans</h2>
          <div role="region" aria-label="Plan comparison" tabIndex={0} className="focus-visible:ring-ring/50 mt-8 overflow-x-auto rounded-3xl border outline-none focus-visible:ring-[3px]">
            <table className="w-full min-w-[34rem] text-start text-sm">
              <thead className="bg-secondary"><tr><th scope="col" className="p-4 font-extrabold">Feature</th>{plans.map((p) => <th key={p.id} scope="col" className="p-4 text-center font-extrabold">{p.name}</th>)}</tr></thead>
              <tbody className="divide-y">{compare.map((r) => <tr key={r[0]}><th scope="row" className="p-4 font-bold">{r[0]}</th>{[r[1], r[2], r[3]].map((v, i) => <td key={i} className="p-4 text-center font-semibold">{cell(v)}</td>)}</tr>)}</tbody>
            </table>
          </div>
        </section>

        <section aria-labelledby="pp-faq" className="mt-24 grid gap-8 lg:grid-cols-[1fr_1.6fr]">
          <h2 id="pp-faq" className={cn("text-[clamp(2rem,5vw,3.5rem)] leading-none", pocketDisplayClass)}>Questions</h2>
          <div className="divide-y border-y">{faqs.map((f) => <details key={f.q} className="py-5"><summary className="focus-visible:ring-ring/50 cursor-pointer list-none rounded-md text-lg font-extrabold outline-none focus-visible:ring-[3px]">{f.q}</summary><p className="text-muted-foreground mt-3 text-pretty">{f.a}</p></details>)}</div>
        </section>
      </main>
    </PocketShell>
  )
}

export { PocketPricing, type PocketPricingProps }
```

### `registry/ballmac/components/templates/pocket/pocket-security.tsx`

```tsx
// Ballmac UI: Pocket security page. https://ui.ballmac.com/templates/template-pocket
"use client"

import * as React from "react"
import { Fingerprint, KeyRound, LockKeyhole, ShieldCheck, Smartphone, Snowflake } from "lucide-react"

import { PocketShell, pocketDisplayClass, type PocketHrefs } from "@/components/ballmac/templates/pocket/pocket-theme"
import { cn } from "@/lib/utils"

const pillars = [
  { icon: Fingerprint, title: "Only you get in", body: "Face or fingerprint on your phone, plus a passkey that never leaves the device. No passwords to leak.", tone: "bg-chart-1" },
  { icon: LockKeyhole, title: "Encrypted end to end", body: "Everything is encrypted in transit and at rest. Card numbers live in a hardware vault, not in a database.", tone: "bg-chart-4" },
  { icon: KeyRound, title: "You decide every payment", body: "Set limits, switch off online or contactless, and approve unusual payments with a tap.", tone: "bg-chart-5" },
  { icon: ShieldCheck, title: "Insured and audited", body: "Deposits are FDIC insured up to $250,000, and independent auditors test us every quarter.", tone: "bg-chart-2" },
]
const steps = [
  { icon: Smartphone, t: "0:00", title: "You notice it’s gone", body: "Open Pocket on any other device and sign in with your passkey." },
  { icon: Snowflake, t: "0:20", title: "Freeze the card", body: "One tap stops every payment. The old phone is signed out at the same time." },
  { icon: LockKeyhole, t: "1:30", title: "Nothing was on the phone", body: "No balances or card numbers are stored on the device, so there is nothing to find." },
  { icon: ShieldCheck, t: "5:00", title: "A new card is on its way", body: "Order a replacement and it arrives in three days. The virtual card works in minutes." },
]

type PocketSecurityProps = React.ComponentProps<"div"> & { hrefs?: Partial<PocketHrefs> }

/** The security page: four pillars, a minute-by-minute lost-phone timeline, live status and a bug bounty. */
function PocketSecurity({ hrefs, ...props }: PocketSecurityProps) {
  return (
    <PocketShell page="security" hrefs={hrefs} {...props}>
      <main className="mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20">
        <section aria-labelledby="pse-title" className="grid items-center gap-10 lg:grid-cols-[1.3fr_1fr]">
          <div>
            <p className="bg-card inline-flex items-center gap-2 rounded-full border px-4 py-1.5 text-sm font-extrabold"><span className="bg-chart-1 size-2.5 rounded-full" aria-hidden="true" />All systems normal · 99.99% uptime this year</p>
            <h1 id="pse-title" className={cn("mt-6 text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance", pocketDisplayClass)}>Boring on purpose.</h1>
            <p className="text-muted-foreground mt-5 max-w-xl text-xl font-medium text-pretty">Money should be the least exciting thing about your phone. This is how we make sure it is.</p>
          </div>
          <div aria-hidden="true" className="relative mx-auto aspect-square w-full max-w-sm">
            <div className="bg-chart-1 absolute inset-[6%] rounded-full" /><div className="bg-[var(--pocket-navy)] absolute inset-[22%] rounded-full" /><ShieldCheck className="text-chart-1 absolute inset-[36%] size-[28%]" strokeWidth={1.6} />
            <span className="bg-card absolute top-[8%] end-[2%] rotate-6 rounded-2xl border px-3 py-1.5 text-sm font-extrabold shadow-lg">256-bit</span><span className="bg-card absolute bottom-[10%] start-[0%] -rotate-6 rounded-2xl border px-3 py-1.5 text-sm font-extrabold shadow-lg">Passkeys</span>
          </div>
        </section>

        <ul className="mt-20 grid gap-4 md:grid-cols-2">{pillars.map((p) => <li key={p.title} className={cn("rounded-[2rem] p-8 text-[var(--pocket-on-lime)] sm:p-10", p.tone)}><p.icon className="size-9" aria-hidden="true" /><h2 className={cn("mt-8 text-3xl", pocketDisplayClass)}>{p.title}</h2><p className="mt-3 text-lg font-medium text-pretty">{p.body}</p></li>)}</ul>

        <section aria-labelledby="pse-lost" className="mt-24">
          <h2 id="pse-lost" className={cn("max-w-2xl text-[clamp(2.2rem,5.5vw,4rem)] leading-[0.95] text-balance", pocketDisplayClass)}>What happens when you lose your phone</h2>
          <ol className="mt-12 grid gap-4 md:grid-cols-4">{steps.map((s, i) => <li key={s.title} className="bg-card relative rounded-3xl border p-6"><span className="text-primary text-sm font-extrabold tabular-nums">{s.t}</span><s.icon className="mt-6 size-7" aria-hidden="true" /><h3 className="mt-4 text-xl font-extrabold text-balance">{s.title}</h3><p className="text-muted-foreground mt-2 text-sm font-medium text-pretty">{s.body}</p><span className="sr-only">Step {i + 1} of {steps.length}</span></li>)}</ol>
        </section>

        <section aria-labelledby="pse-bounty" className="mt-24 grid gap-4 lg:grid-cols-2">
          <div className="bg-[var(--pocket-navy)] rounded-[2rem] p-8 text-[var(--pocket-on-navy)] sm:p-12"><h2 id="pse-bounty" className={cn("text-4xl", pocketDisplayClass)}>Find a bug, get paid.</h2><p className="mt-3 text-lg font-medium text-pretty">Our bug bounty pays up to $50,000 for serious findings. We publish every fixed report and credit the researcher.</p><p className={cn("text-chart-1 mt-8 text-7xl leading-none tabular-nums", pocketDisplayClass)}>$50k</p></div>
          <div className="bg-card rounded-[2rem] border p-8 sm:p-12"><h2 className={cn("text-4xl", pocketDisplayClass)}>Checked by others</h2><ul className="mt-6 grid grid-cols-2 gap-3">{["SOC 2 Type II", "ISO 27001", "PCI DSS Level 1", "FDIC insured"].map((c) => <li key={c} className="bg-secondary flex items-center gap-2 rounded-2xl p-4 text-sm font-extrabold"><ShieldCheck className="size-5 shrink-0" aria-hidden="true" />{c}</li>)}</ul><p className="text-muted-foreground mt-6 text-sm font-medium">Reports are available to customers on request. Last audit: August 2026.</p></div>
        </section>
      </main>
    </PocketShell>
  )
}

export { PocketSecurity, type PocketSecurityProps }
```

### `registry/ballmac/components/templates/pocket/pocket-download.tsx`

```tsx
// Ballmac UI: Pocket download page. https://ui.ballmac.com/templates/template-pocket
"use client"

import * as React from "react"
import { Check, Smartphone } from "lucide-react"

import { PocketApp, PocketShell, StoreButtons, pocketDisplayClass, type PocketHrefs } from "@/components/ballmac/templates/pocket/pocket-theme"
import { cn } from "@/lib/utils"

/** A decorative QR-style code: three finder squares and a fixed pseudo-random fill, so server and client agree. */
function QrArt({ className }: { className?: string }) {
  const n = 21
  const finder = (x: number, y: number) => (x < 7 && y < 7) || (x >= n - 7 && y < 7) || (x < 7 && y >= n - 7)
  const cells: React.ReactNode[] = []
  let seed = 7
  for (let y = 0; y < n; y++)
    for (let x = 0; x < n; x++) {
      seed = (seed * 1103515245 + 12345) & 0x7fffffff
      if (finder(x, y)) continue
      if ((seed >> 8) % 100 < 46) cells.push(<rect key={`${x}-${y}`} x={x} y={y} width="1" height="1" />)
    }
  const eye = (x: number, y: number) => (
    <g key={`${x}${y}`}><rect x={x} y={y} width="7" height="7" /><rect x={x + 1} y={y + 1} width="5" height="5" className="fill-card" /><rect x={x + 2} y={y + 2} width="3" height="3" /></g>
  )
  return (
    <svg viewBox={`-1 -1 ${n + 2} ${n + 2}`} role="img" aria-label="QR code that opens the download page on your phone" className={cn("bg-card fill-[var(--pocket-ink)] dark:fill-foreground rounded-2xl p-1", className)}>
      {cells}{eye(0, 0)}{eye(n - 7, 0)}{eye(0, n - 7)}
    </svg>
  )
}

type PocketDownloadProps = React.ComponentProps<"div"> & { hrefs?: Partial<PocketHrefs> }

/** The download page: store buttons, a QR code, and a “text me the link” form that validates and confirms. */
function PocketDownload({ hrefs, ...props }: PocketDownloadProps) {
  const link = { download: "/pocket/download", ...hrefs }
  const [value, setValue] = React.useState("")
  const [device, setDevice] = React.useState<"iphone" | "android">("iphone")
  const [error, setError] = React.useState("")
  const [sent, setSent] = React.useState<string | null>(null)
  function submit(e: React.FormEvent) {
    e.preventDefault()
    const v = value.trim()
    const ok = /^\S+@\S+\.\S+$/.test(v) || v.replace(/\D/g, "").length >= 10
    if (!ok) return setError("Enter a mobile number or an email address.")
    setError("")
    setSent(v)
  }
  return (
    <PocketShell page="download" hrefs={hrefs} {...props}>
      <main className="mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20">
        <div className="grid items-center gap-12 lg:grid-cols-[1.2fr_1fr]">
          <div>
            <h1 className={cn("text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance", pocketDisplayClass)}>Get Pocket in your pocket.</h1>
            <p className="text-muted-foreground mt-5 max-w-lg text-xl font-medium text-pretty">Free on iPhone and Android. Open an account in about four minutes, with a photo ID and your phone.</p>
            <StoreButtons href={link.download} className="mt-8" />

            <section aria-labelledby="pd-text" className="bg-card mt-10 rounded-[2rem] border p-6 sm:p-8">
              <h2 id="pd-text" className={cn("flex items-center gap-2 text-2xl", pocketDisplayClass)}><Smartphone className="size-6" aria-hidden="true" />On your computer? Text yourself the link.</h2>
              {sent ? (
                <p role="status" className="bg-chart-1 mt-5 flex items-center gap-2 rounded-2xl p-4 font-extrabold text-[var(--pocket-on-lime)]"><Check className="size-5 shrink-0" aria-hidden="true" />Sent to {sent}. Open it on your {device === "iphone" ? "iPhone" : "Android"}.</p>
              ) : (
                <form onSubmit={submit} noValidate className="mt-5 grid gap-4">
                  <fieldset><legend className="mb-2 text-sm font-extrabold">Your phone</legend>
                    <div className="flex gap-2">{([["iphone", "iPhone"], ["android", "Android"]] as const).map(([v, l]) => <label key={v} className={cn("focus-within:ring-ring/50 cursor-pointer rounded-full border-2 px-5 py-2.5 text-sm font-extrabold transition-colors focus-within:ring-[3px] motion-reduce:transition-none", device === v ? "border-primary bg-primary text-primary-foreground" : "hover:border-primary/40")}><input type="radio" name="device" value={v} checked={device === v} onChange={() => setDevice(v)} className="sr-only" />{l}</label>)}</div>
                  </fieldset>
                  <div className="grid gap-2"><label htmlFor="pd-contact" className="text-sm font-extrabold">Mobile number or email</label>
                    <div className="flex flex-col gap-2 sm:flex-row"><input id="pd-contact" value={value} onChange={(e) => setValue(e.target.value)} aria-invalid={!!error} aria-describedby={error ? "pd-err" : undefined} placeholder="(555) 010-2030" className="bg-background focus-visible:ring-ring/50 aria-invalid:border-destructive h-14 min-w-0 flex-1 rounded-full border-2 px-6 text-lg font-bold outline-none focus-visible:ring-[3px]" /><button type="submit" className="bg-primary text-primary-foreground focus-visible:ring-ring/50 h-14 rounded-full px-8 text-lg font-extrabold outline-none focus-visible:ring-[3px]">Text me the link</button></div>
                    {error && <p id="pd-err" role="alert" className="text-destructive text-sm font-bold">{error}</p>}
                  </div>
                  <p className="text-muted-foreground text-xs font-medium">We send one message and do not keep your number.</p>
                </form>
              )}
            </section>
          </div>

          <div className="relative mx-auto grid w-full max-w-sm justify-items-center gap-6">
            <PocketApp defaultTab="save" className="w-[min(100%,290px)]" />
            <div className="bg-chart-1 relative z-10 -mt-20 flex items-center gap-4 self-end rounded-3xl p-4 text-[var(--pocket-on-lime)] shadow-xl sm:-me-8"><QrArt className="size-24" /><p className="max-w-[9rem] text-sm font-extrabold">Point your camera here to download</p></div>
          </div>
        </div>

        <section aria-labelledby="pd-need" className="mt-24 grid gap-4 md:grid-cols-3">
          <h2 id="pd-need" className="sr-only">What you need</h2>
          {[["A phone", "iOS 16 or later, or Android 10 or later. Face or fingerprint unlock turned on."], ["A photo ID", "A passport or driver’s licence. We check it in the app, usually in under a minute."], ["Four minutes", "That is the median. You can fund the account straight away from a bank account or card."]].map(([t, b]) => <div key={t} className="bg-secondary rounded-3xl p-7"><h3 className={cn("text-2xl", pocketDisplayClass)}>{t}</h3><p className="text-muted-foreground mt-2 font-medium text-pretty">{b}</p></div>)}
        </section>
      </main>
    </PocketShell>
  )
}

export { PocketDownload, QrArt, type PocketDownloadProps }
```

### `registry/ballmac/app/pocket/page.tsx`

```tsx
// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket
import type { Metadata } from "next"

import { PocketHome } from "@/components/ballmac/templates/pocket/pocket-home"

export const metadata: Metadata = {
  title: "Pocket: money that keeps up",
  description: "One app for spending, saving and splitting. No fees to open or to leave.",
}

export default function Page() {
  return <PocketHome />
}
```

### `registry/ballmac/app/pocket/features/page.tsx`

```tsx
// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket
import type { Metadata } from "next"

import { PocketFeatures } from "@/components/ballmac/templates/pocket/pocket-features"

export const metadata: Metadata = {
  title: "Features · Pocket",
  description: "Freeze a card, tune round-ups, split a bill and convert money, live.",
}

export default function Page() {
  return <PocketFeatures />
}
```

### `registry/ballmac/app/pocket/pricing/page.tsx`

```tsx
// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket
import type { Metadata } from "next"

import { PocketPricing } from "@/components/ballmac/templates/pocket/pocket-pricing"

export const metadata: Metadata = {
  title: "Pricing · Pocket",
  description: "Free forever, with Plus and Metal for extras.",
}

export default function Page() {
  return <PocketPricing />
}
```

### `registry/ballmac/app/pocket/security/page.tsx`

```tsx
// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket
import type { Metadata } from "next"

import { PocketSecurity } from "@/components/ballmac/templates/pocket/pocket-security"

export const metadata: Metadata = {
  title: "Security · Pocket",
  description: "How Pocket keeps your money safe, and what happens if you lose your phone.",
}

export default function Page() {
  return <PocketSecurity />
}
```

### `registry/ballmac/app/pocket/download/page.tsx`

```tsx
// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket
import type { Metadata } from "next"

import { PocketDownload } from "@/components/ballmac/templates/pocket/pocket-download"

export const metadata: Metadata = {
  title: "Download · Pocket",
  description: "Free on iPhone and Android.",
}

export default function Page() {
  return <PocketDownload />
}
```
