{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "template-pocket",
  "title": "Pocket: mobile money app",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "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.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.ballmac.com/r/phone-frame.json",
    "https://ui.ballmac.com/r/switch.json",
    "https://ui.ballmac.com/r/slider.json"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-fonts.ts",
      "content": "// Ballmac UI: Pocket template fonts. https://ui.ballmac.com/templates/template-pocket\nimport { Gabarito } from \"next/font/google\"\n\nexport const pocketSans = Gabarito({ variable: \"--pocket-sans\", subsets: [\"latin\"], display: \"swap\", preload: false })\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-fonts.ts"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-data.ts",
      "content": "// Ballmac UI: Pocket template data. https://ui.ballmac.com/templates/template-pocket\nexport const transactions = [\n  { name: \"Corner Café\", detail: \"Today, 8:12\", amount: -4.8, tone: 1, emoji: \"☕\" },\n  { name: \"From Sam\", detail: \"Yesterday\", amount: 120, tone: 0, emoji: \"↓\" },\n  { name: \"City Transit\", detail: \"Yesterday\", amount: -2.75, tone: 3, emoji: \"🚆\" },\n  { name: \"Market Hall\", detail: \"Monday\", amount: -38.12, tone: 2, emoji: \"🥬\" },\n  { name: \"Pilates Studio\", detail: \"Sunday\", amount: -22, tone: 4, emoji: \"🧘\" },\n]\n\nexport type Plan = { id: string; name: string; monthly: number; annual: number; blurb: string; features: string[]; featured?: boolean }\nexport const plans: Plan[] = [\n  { 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\"] },\n  { 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 },\n  { 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\"] },\n]\n\nexport const compare = [\n  [\"Virtual card\", true, true, true],\n  [\"Physical card\", \"$5\", true, true],\n  [\"Savings pots\", \"1\", \"Unlimited\", \"Unlimited\"],\n  [\"Foreign spending fee\", \"1.5%\", \"None\", \"None\"],\n  [\"ATM withdrawals a month\", \"$200\", \"$800\", \"Unlimited\"],\n  [\"Bill splitting\", false, true, true],\n  [\"Cashback\", false, false, \"1%\"],\n  [\"Support\", \"Chat\", \"Priority chat\", \"24/7 phone\"],\n] as const\n\nexport const faqs = [\n  { 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.\" },\n  { 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.\" },\n  { 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.\" },\n  { 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.\" },\n  { q: \"Which countries does it work in?\", a: \"The card works anywhere Visa does. Sending money to friends is available in 31 countries today.\" },\n  { 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.\" },\n]\n\nexport const currencies = [[\"USD\", 1, \"$\"], [\"EUR\", 0.92, \"€\"], [\"GBP\", 0.79, \"£\"], [\"JPY\", 156.4, \"¥\"], [\"MXN\", 17.1, \"MX$\"]] as const\n\nexport const money = (n: number, digits = 2) => `${n < 0 ? \"−\" : \"\"}$${Math.abs(n).toLocaleString(\"en-US\", { minimumFractionDigits: digits, maximumFractionDigits: digits })}`\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-data.ts"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-theme.tsx",
      "content": "// Ballmac UI: Pocket template shell. https://ui.ballmac.com/templates/template-pocket\n\"use client\"\n\nimport * as React from \"react\"\nimport { Apple, Bell, CreditCard, Home as HomeIcon, Menu, PiggyBank, Play, QrCode, Send, X } from \"lucide-react\"\n\nimport { PhoneFrame } from \"@/components/ballmac/phone-frame\"\nimport { Switch } from \"@/components/ballmac/switch\"\nimport { money, transactions } from \"@/components/ballmac/templates/pocket/pocket-data\"\nimport { pocketSans } from \"@/components/ballmac/templates/pocket/pocket-fonts\"\nimport { cn } from \"@/lib/utils\"\n\ntype PocketPage = \"home\" | \"features\" | \"pricing\" | \"security\" | \"download\"\ntype PocketHrefs = Record<PocketPage, string>\n\nconst defaultHrefs: PocketHrefs = { home: \"/pocket\", features: \"/pocket/features\", pricing: \"/pocket/pricing\", security: \"/pocket/security\", download: \"/pocket/download\" }\n\n/** Pocket's palette: mint paper, navy ink, cobalt and one loud lime. Dark mode is midnight with the lime turned up. */\nconst pocketCss = `\n.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}\n.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)}\nbody:not(:has([data-gallery])):has(.pocket-theme){font-family:var(--pocket-sans),ui-sans-serif,system-ui,sans-serif}\n@keyframes pocket-bob{0%,100%{transform:translateY(0) rotate(var(--r,0deg))}50%{transform:translateY(-8px) rotate(var(--r,0deg))}}\n.pocket-bob{animation:pocket-bob 5s ease-in-out infinite}\n@media (prefers-reduced-motion:reduce){.pocket-bob{animation:none}}\n`\n\nconst display = \"font-black tracking-[-0.035em]\"\nconst onLime = \"text-[var(--pocket-on-lime)]\"\nconst txTone = [\"bg-chart-1\", \"bg-chart-5\", \"bg-chart-4\", \"bg-chart-2\", \"bg-chart-3\"]\n\n/** The Pocket app inside a phone: balance, quick actions and three tabs (Home, Card, Save). Tap around. */\nfunction PocketApp({ className, defaultTab = \"home\" }: { className?: string; defaultTab?: \"home\" | \"card\" | \"save\" }) {\n  const [tab, setTab] = React.useState<\"home\" | \"card\" | \"save\">(defaultTab)\n  const [frozen, setFrozen] = React.useState(false)\n  const id = React.useId()\n  const tabs = [[\"home\", \"Home\", HomeIcon], [\"card\", \"Card\", CreditCard], [\"save\", \"Save\", PiggyBank]] as const\n  return (\n    <PhoneFrame screenWidth={390} className={cn(\"w-[min(100%,290px)]\", className)} screenClassName=\"pocket-theme bg-background text-foreground\">\n      <div className=\"flex h-full flex-col text-[15px]\" style={{ fontFamily: \"var(--pocket-sans), ui-sans-serif, system-ui, sans-serif\" }}>\n        <div className=\"flex items-center justify-between px-5 pt-2\">\n          <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>\n          <span aria-hidden=\"true\" className=\"bg-secondary flex size-10 items-center justify-center rounded-full\"><Bell className=\"size-5\" /></span>\n        </div>\n        <div role=\"tabpanel\" id={`${id}-panel`} aria-labelledby={`${id}-${tab}`} className=\"min-h-0 flex-1 overflow-hidden px-5 pt-4\">\n          {tab === \"home\" && (\n            <>\n              <div className=\"bg-primary text-primary-foreground rounded-3xl p-5\">\n                <p className=\"text-sm font-semibold\">Total balance</p>\n                <p className={cn(\"mt-1 text-[40px] leading-none tabular-nums\", display)}>$12,480<span className=\"text-2xl opacity-100\">.62</span></p>\n                <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>\n              </div>\n              <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>\n              <p className=\"mt-4 text-sm font-extrabold\">Recent</p>\n              <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>\n            </>\n          )}\n          {tab === \"card\" && (\n            <>\n              <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\")}>\n                <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\" />\n                <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>\n                {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>}\n              </div>\n              <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>\n              <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>\n            </>\n          )}\n          {tab === \"save\" && (\n            <>\n              <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>\n              <p className=\"mt-4 text-sm font-extrabold\">Round-ups this month</p>\n              <p className={cn(\"text-3xl tabular-nums\", display)}>$37.20</p>\n              <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>\n            </>\n          )}\n        </div>\n        <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\">\n          {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>)}\n        </div>\n      </div>\n    </PhoneFrame>\n  )\n}\n\n/** App Store and Google Play buttons that go to the download page. */\nfunction StoreButtons({ href, className }: { href: string; className?: string }) {\n  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-0.5 focus-visible:ring-[3px] motion-reduce:transition-none motion-reduce:hover:translate-y-0\"\n  return (\n    <div className={cn(\"flex flex-wrap gap-3\", className)}>\n      <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>\n      <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>\n    </div>\n  )\n}\n\nconst links: { key: PocketPage; label: string }[] = [{ key: \"features\", label: \"Features\" }, { key: \"pricing\", label: \"Pricing\" }, { key: \"security\", label: \"Security\" }]\n\ntype PocketShellProps = React.ComponentProps<\"div\"> & {\n  /** The page being shown, so its nav link is marked current. */\n  page: PocketPage\n  /** Override where pages live (used by previews). */\n  hrefs?: Partial<PocketHrefs>\n}\n\n/** Pocket's frame: a floating pill header, and a navy footer with a giant wordmark. */\nfunction PocketShell({ page, hrefs: overrides, className, style, children, ...props }: PocketShellProps) {\n  const hrefs = { ...defaultHrefs, ...overrides }\n  const [open, setOpen] = React.useState(false)\n  React.useEffect(() => {\n    const classes = [pocketSans.variable].filter(Boolean)\n    document.body.classList.add(...classes)\n    return () => document.body.classList.remove(...classes)\n  }, [])\n  return (\n    <div\n      data-slot=\"pocket\"\n      className={cn(\"pocket-theme bg-background text-foreground relative min-h-dvh overflow-x-clip\", pocketSans.variable, className)}\n      style={{ fontFamily: \"var(--pocket-sans), ui-sans-serif, system-ui, sans-serif\", ...style }}\n      {...props}\n    >\n      <style>{pocketCss}</style>\n      <header className=\"sticky top-3 z-40 px-3 sm:px-6\">\n        <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\">\n          <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>\n          <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>\n          <div className=\"flex items-center gap-1\">\n            <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>\n            <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>\n          </div>\n        </div>\n        {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>}\n      </header>\n      {children}\n      <footer className=\"mt-24 overflow-hidden bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)]\">\n        <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]\">\n          <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>\n          {[[\"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>)}\n        </div>\n        <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>\n        <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>\n      </footer>\n    </div>\n  )\n}\n\nexport { PocketApp, PocketShell, StoreButtons, defaultHrefs as pocketDefaultHrefs, display as pocketDisplayClass, onLime as pocketOnLime, type PocketHrefs, type PocketPage, type PocketShellProps }\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-theme.tsx"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-home.tsx",
      "content": "// Ballmac UI: Pocket home page. https://ui.ballmac.com/templates/template-pocket\n\"use client\"\n\nimport * as React from \"react\"\nimport { ArrowRight, Globe2, PiggyBank, ShieldCheck, Snowflake, Users } from \"lucide-react\"\n\nimport { PocketApp, PocketShell, StoreButtons, pocketDisplayClass, type PocketHrefs } from \"@/components/ballmac/templates/pocket/pocket-theme\"\nimport { cn } from \"@/lib/utils\"\n\nconst cards = [\n  { 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\" },\n  { 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\" },\n  { 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\" },\n  { 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\" },\n]\nconst reviews = [\n  [\"It’s the first money app I open on purpose.\", \"Priya N.\", \"App Store\"],\n  [\"Round-ups paid for our entire holiday. I did nothing.\", \"Tom & Lucia\", \"Google Play\"],\n  [\"Froze my card from a taxi in Lisbon. Unfroze it at the hotel.\", \"Dev R.\", \"App Store\"],\n]\n\ntype PocketHomeProps = React.ComponentProps<\"div\"> & { hrefs?: Partial<PocketHrefs> }\n\n/** The Pocket home page: a hero with a working app in a phone, four feature blocks, proof and the download buttons. */\nfunction PocketHome({ hrefs, ...props }: PocketHomeProps) {\n  const link = { features: \"/pocket/features\", pricing: \"/pocket/pricing\", download: \"/pocket/download\", security: \"/pocket/security\", ...hrefs }\n  return (\n    <PocketShell page=\"home\" hrefs={hrefs} {...props}>\n      <main>\n        <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\">\n          <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\" />\n          <div>\n            <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>\n            <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>\n            <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>\n            <StoreButtons href={link.download} className=\"mt-8\" />\n            <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>\n          </div>\n          <div className=\"relative mx-auto w-full max-w-sm\">\n            <PocketApp className=\"mx-auto w-[min(100%,300px)]\" />\n            <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>\n            <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>\n          </div>\n        </section>\n\n        <section aria-label=\"Featured in\" className=\"border-y\">\n          <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>\n        </section>\n\n        <section aria-labelledby=\"ph-feat\" className=\"mx-auto max-w-6xl px-4 py-20 sm:px-6\">\n          <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>\n          <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>\n          <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>\n        </section>\n\n        <section aria-label=\"Pocket in numbers\" className=\"bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)]\">\n          <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>\n        </section>\n\n        <section aria-labelledby=\"ph-rev\" className=\"mx-auto max-w-6xl px-4 py-20 sm:px-6\">\n          <h2 id=\"ph-rev\" className={cn(\"text-[clamp(2.4rem,6vw,4rem)] leading-none\", pocketDisplayClass)}>People say nice things</h2>\n          <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>\n        </section>\n\n        <section aria-labelledby=\"ph-cta\" className=\"mx-auto max-w-6xl px-4 pb-8 sm:px-6\">\n          <div className=\"bg-primary text-primary-foreground rounded-[2.5rem] px-6 py-16 text-center sm:px-14\">\n            <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>\n            <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>\n            <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>\n          </div>\n        </section>\n      </main>\n    </PocketShell>\n  )\n}\n\nexport { PocketHome, type PocketHomeProps }\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-home.tsx"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-features.tsx",
      "content": "// Ballmac UI: Pocket features page. https://ui.ballmac.com/templates/template-pocket\n\"use client\"\n\nimport * as React from \"react\"\nimport { Send, Snowflake } from \"lucide-react\"\n\nimport { Slider } from \"@/components/ballmac/slider\"\nimport { Switch } from \"@/components/ballmac/switch\"\nimport { currencies, money } from \"@/components/ballmac/templates/pocket/pocket-data\"\nimport { PocketShell, pocketDisplayClass, type PocketHrefs } from \"@/components/ballmac/templates/pocket/pocket-theme\"\nimport { cn } from \"@/lib/utils\"\n\nconst bars = [[\"Food\", 340, \"bg-chart-1\"], [\"Travel\", 215, \"bg-chart-4\"], [\"Fun\", 180, \"bg-chart-5\"], [\"Home\", 120, \"bg-chart-2\"]] as const\nconst people = [[\"Sam\", \"bg-chart-1\", true], [\"Ana\", \"bg-chart-4\", true], [\"Joe\", \"bg-chart-5\", false], [\"Mei\", \"bg-chart-2\", false]] as const\n\ntype PocketFeaturesProps = React.ComponentProps<\"div\"> & { hrefs?: Partial<PocketHrefs> }\n\n/** The features page: five live demos instead of five screenshots. Freeze a card, tune round-ups, split a bill, convert money. */\nfunction PocketFeatures({ hrefs, ...props }: PocketFeaturesProps) {\n  const [frozen, setFrozen] = React.useState(false)\n  const [spend, setSpend] = React.useState(900)\n  const [paid, setPaid] = React.useState<string[]>([\"Sam\", \"Ana\"])\n  const [amount, setAmount] = React.useState(\"100\")\n  const [cur, setCur] = React.useState<(typeof currencies)[number][0]>(\"EUR\")\n  const savedPerMonth = Math.round(spend * 0.045)\n  const rate = currencies.find((c) => c[0] === cur)!\n  const converted = (Number(amount) || 0) * rate[1]\n  const bill = 128\n  const share = bill / people.length\n  const total = bars.reduce((n, b) => n + b[1], 0)\n  const card = \"rounded-[2rem] border p-8 sm:p-10\"\n  return (\n    <PocketShell page=\"features\" hrefs={hrefs} {...props}>\n      <main className=\"mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20\">\n        <h1 className={cn(\"max-w-3xl text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance\", pocketDisplayClass)}>Try it right here.</h1>\n        <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>\n\n        <div className=\"mt-14 grid gap-4 lg:grid-cols-6\">\n          <section aria-labelledby=\"pf-card\" className={cn(card, \"bg-[var(--pocket-navy)] text-[var(--pocket-on-navy)] lg:col-span-3\")}>\n            <h2 id=\"pf-card\" className={cn(\"text-3xl\", pocketDisplayClass)}>Freeze it in one tap</h2>\n            <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>\n            <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\")}>\n              <p className={cn(\"text-2xl\", pocketDisplayClass)}>pocket</p><p className=\"mt-12 text-xl font-bold tracking-widest tabular-nums\">•••• •••• •••• 4821</p>\n              {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>}\n            </div>\n            <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>\n            <p role=\"status\" className=\"mt-3 text-sm font-semibold\">{frozen ? \"Payments are off. Nothing can be charged.\" : \"Your card is live.\"}</p>\n          </section>\n\n          <section aria-labelledby=\"pf-round\" className={cn(card, \"bg-chart-1 text-[var(--pocket-on-lime)] lg:col-span-3\")}>\n            <h2 id=\"pf-round\" className={cn(\"text-3xl\", pocketDisplayClass)}>Round-ups, calculated</h2>\n            <p className=\"mt-2 max-w-sm font-medium text-pretty\">Tell us roughly what you spend on your card each month.</p>\n            <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>\n            <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\" />\n            <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>\n          </section>\n\n          <section aria-labelledby=\"pf-ins\" className={cn(card, \"bg-card lg:col-span-2\")}>\n            <h2 id=\"pf-ins\" className={cn(\"text-3xl\", pocketDisplayClass)}>Where it went</h2>\n            <p className=\"text-muted-foreground mt-2 text-lg font-medium\">{money(total, 0)} in August</p>\n            <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>\n          </section>\n\n          <section aria-labelledby=\"pf-split\" className={cn(card, \"bg-card lg:col-span-2\")}>\n            <h2 id=\"pf-split\" className={cn(\"text-3xl\", pocketDisplayClass)}>Split the bill</h2>\n            <p className=\"text-muted-foreground mt-2 font-medium\">Dinner, {money(bill, 0)} · {money(share, 0)} each</p>\n            <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>\n            <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>\n          </section>\n\n          <section aria-labelledby=\"pf-fx\" className={cn(card, \"bg-chart-4 text-[var(--pocket-on-lime)] lg:col-span-2\")}>\n            <h2 id=\"pf-fx\" className={cn(\"text-3xl\", pocketDisplayClass)}>Real exchange rate</h2>\n            <p className=\"mt-2 font-medium\">No fee, no markup.</p>\n            <div className=\"mt-6 grid gap-3\">\n              <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>\n              <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>\n              <p className=\"mt-2 font-extrabold\">They receive</p>\n              <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>\n              <p className=\"text-sm font-bold\">1 USD = {rate[1]} {cur}</p>\n            </div>\n          </section>\n        </div>\n      </main>\n    </PocketShell>\n  )\n}\n\nexport { PocketFeatures, type PocketFeaturesProps }\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-features.tsx"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-pricing.tsx",
      "content": "// Ballmac UI: Pocket pricing page. https://ui.ballmac.com/templates/template-pocket\n\"use client\"\n\nimport * as React from \"react\"\nimport { Check, Minus } from \"lucide-react\"\n\nimport { compare, faqs, plans } from \"@/components/ballmac/templates/pocket/pocket-data\"\nimport { PocketShell, pocketDisplayClass, type PocketHrefs } from \"@/components/ballmac/templates/pocket/pocket-theme\"\nimport { cn } from \"@/lib/utils\"\n\ntype PocketPricingProps = React.ComponentProps<\"div\"> & { hrefs?: Partial<PocketHrefs> }\n\n/** Pricing: a monthly or yearly switch, three plans, a real comparison table and the questions people ask. */\nfunction PocketPricing({ hrefs, ...props }: PocketPricingProps) {\n  const link = { download: \"/pocket/download\", ...hrefs }\n  const [yearly, setYearly] = React.useState(true)\n  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)\n  return (\n    <PocketShell page=\"pricing\" hrefs={hrefs} {...props}>\n      <main className=\"mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20\">\n        <div className=\"text-center\">\n          <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>\n          <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>\n          <div role=\"group\" aria-label=\"Billing period\" className=\"bg-secondary mt-8 inline-flex rounded-full p-1\">\n            {([[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>)}\n          </div>\n        </div>\n\n        <ul className=\"mt-12 grid gap-4 lg:grid-cols-3\">\n          {plans.map((p) => {\n            const price = yearly ? p.annual : p.monthly\n            return (\n              <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\")}>\n                {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>}\n                <h2 className={cn(\"text-2xl\", pocketDisplayClass)}>{p.name}</h2>\n                <p className=\"mt-1 text-sm font-medium\">{p.blurb}</p>\n                <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>\n                <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>\n                <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>\n                <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>\n              </li>\n            )\n          })}\n        </ul>\n\n        <section aria-labelledby=\"pp-compare\" className=\"mt-24\">\n          <h2 id=\"pp-compare\" className={cn(\"text-[clamp(2rem,5vw,3.5rem)] leading-none\", pocketDisplayClass)}>Compare plans</h2>\n          <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]\">\n            <table className=\"w-full min-w-[34rem] text-start text-sm\">\n              <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>\n              <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>\n            </table>\n          </div>\n        </section>\n\n        <section aria-labelledby=\"pp-faq\" className=\"mt-24 grid gap-8 lg:grid-cols-[1fr_1.6fr]\">\n          <h2 id=\"pp-faq\" className={cn(\"text-[clamp(2rem,5vw,3.5rem)] leading-none\", pocketDisplayClass)}>Questions</h2>\n          <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>\n        </section>\n      </main>\n    </PocketShell>\n  )\n}\n\nexport { PocketPricing, type PocketPricingProps }\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-pricing.tsx"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-security.tsx",
      "content": "// Ballmac UI: Pocket security page. https://ui.ballmac.com/templates/template-pocket\n\"use client\"\n\nimport * as React from \"react\"\nimport { Fingerprint, KeyRound, LockKeyhole, ShieldCheck, Smartphone, Snowflake } from \"lucide-react\"\n\nimport { PocketShell, pocketDisplayClass, type PocketHrefs } from \"@/components/ballmac/templates/pocket/pocket-theme\"\nimport { cn } from \"@/lib/utils\"\n\nconst pillars = [\n  { 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\" },\n  { 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\" },\n  { 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\" },\n  { 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\" },\n]\nconst steps = [\n  { icon: Smartphone, t: \"0:00\", title: \"You notice it’s gone\", body: \"Open Pocket on any other device and sign in with your passkey.\" },\n  { 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.\" },\n  { 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.\" },\n  { 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.\" },\n]\n\ntype PocketSecurityProps = React.ComponentProps<\"div\"> & { hrefs?: Partial<PocketHrefs> }\n\n/** The security page: four pillars, a minute-by-minute lost-phone timeline, live status and a bug bounty. */\nfunction PocketSecurity({ hrefs, ...props }: PocketSecurityProps) {\n  return (\n    <PocketShell page=\"security\" hrefs={hrefs} {...props}>\n      <main className=\"mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20\">\n        <section aria-labelledby=\"pse-title\" className=\"grid items-center gap-10 lg:grid-cols-[1.3fr_1fr]\">\n          <div>\n            <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>\n            <h1 id=\"pse-title\" className={cn(\"mt-6 text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance\", pocketDisplayClass)}>Boring on purpose.</h1>\n            <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>\n          </div>\n          <div aria-hidden=\"true\" className=\"relative mx-auto aspect-square w-full max-w-sm\">\n            <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} />\n            <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>\n          </div>\n        </section>\n\n        <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>\n\n        <section aria-labelledby=\"pse-lost\" className=\"mt-24\">\n          <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>\n          <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>\n        </section>\n\n        <section aria-labelledby=\"pse-bounty\" className=\"mt-24 grid gap-4 lg:grid-cols-2\">\n          <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>\n          <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>\n        </section>\n      </main>\n    </PocketShell>\n  )\n}\n\nexport { PocketSecurity, type PocketSecurityProps }\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-security.tsx"
    },
    {
      "path": "registry/ballmac/components/templates/pocket/pocket-download.tsx",
      "content": "// Ballmac UI: Pocket download page. https://ui.ballmac.com/templates/template-pocket\n\"use client\"\n\nimport * as React from \"react\"\nimport { Check, Smartphone } from \"lucide-react\"\n\nimport { PocketApp, PocketShell, StoreButtons, pocketDisplayClass, type PocketHrefs } from \"@/components/ballmac/templates/pocket/pocket-theme\"\nimport { cn } from \"@/lib/utils\"\n\n/** A decorative QR-style code: three finder squares and a fixed pseudo-random fill, so server and client agree. */\nfunction QrArt({ className }: { className?: string }) {\n  const n = 21\n  const finder = (x: number, y: number) => (x < 7 && y < 7) || (x >= n - 7 && y < 7) || (x < 7 && y >= n - 7)\n  const cells: React.ReactNode[] = []\n  let seed = 7\n  for (let y = 0; y < n; y++)\n    for (let x = 0; x < n; x++) {\n      seed = (seed * 1103515245 + 12345) & 0x7fffffff\n      if (finder(x, y)) continue\n      if ((seed >> 8) % 100 < 46) cells.push(<rect key={`${x}-${y}`} x={x} y={y} width=\"1\" height=\"1\" />)\n    }\n  const eye = (x: number, y: number) => (\n    <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>\n  )\n  return (\n    <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)}>\n      {cells}{eye(0, 0)}{eye(n - 7, 0)}{eye(0, n - 7)}\n    </svg>\n  )\n}\n\ntype PocketDownloadProps = React.ComponentProps<\"div\"> & { hrefs?: Partial<PocketHrefs> }\n\n/** The download page: store buttons, a QR code, and a “text me the link” form that validates and confirms. */\nfunction PocketDownload({ hrefs, ...props }: PocketDownloadProps) {\n  const link = { download: \"/pocket/download\", ...hrefs }\n  const [value, setValue] = React.useState(\"\")\n  const [device, setDevice] = React.useState<\"iphone\" | \"android\">(\"iphone\")\n  const [error, setError] = React.useState(\"\")\n  const [sent, setSent] = React.useState<string | null>(null)\n  function submit(e: React.FormEvent) {\n    e.preventDefault()\n    const v = value.trim()\n    const ok = /^\\S+@\\S+\\.\\S+$/.test(v) || v.replace(/\\D/g, \"\").length >= 10\n    if (!ok) return setError(\"Enter a mobile number or an email address.\")\n    setError(\"\")\n    setSent(v)\n  }\n  return (\n    <PocketShell page=\"download\" hrefs={hrefs} {...props}>\n      <main className=\"mx-auto max-w-6xl px-4 pt-14 pb-8 sm:px-6 sm:pt-20\">\n        <div className=\"grid items-center gap-12 lg:grid-cols-[1.2fr_1fr]\">\n          <div>\n            <h1 className={cn(\"text-[clamp(3rem,9vw,7rem)] leading-[0.9] text-balance\", pocketDisplayClass)}>Get Pocket in your pocket.</h1>\n            <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>\n            <StoreButtons href={link.download} className=\"mt-8\" />\n\n            <section aria-labelledby=\"pd-text\" className=\"bg-card mt-10 rounded-[2rem] border p-6 sm:p-8\">\n              <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>\n              {sent ? (\n                <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>\n              ) : (\n                <form onSubmit={submit} noValidate className=\"mt-5 grid gap-4\">\n                  <fieldset><legend className=\"mb-2 text-sm font-extrabold\">Your phone</legend>\n                    <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>\n                  </fieldset>\n                  <div className=\"grid gap-2\"><label htmlFor=\"pd-contact\" className=\"text-sm font-extrabold\">Mobile number or email</label>\n                    <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>\n                    {error && <p id=\"pd-err\" role=\"alert\" className=\"text-destructive text-sm font-bold\">{error}</p>}\n                  </div>\n                  <p className=\"text-muted-foreground text-xs font-medium\">We send one message and do not keep your number.</p>\n                </form>\n              )}\n            </section>\n          </div>\n\n          <div className=\"relative mx-auto grid w-full max-w-sm justify-items-center gap-6\">\n            <PocketApp defaultTab=\"save\" className=\"w-[min(100%,290px)]\" />\n            <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>\n          </div>\n        </div>\n\n        <section aria-labelledby=\"pd-need\" className=\"mt-24 grid gap-4 md:grid-cols-3\">\n          <h2 id=\"pd-need\" className=\"sr-only\">What you need</h2>\n          {[[\"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>)}\n        </section>\n      </main>\n    </PocketShell>\n  )\n}\n\nexport { PocketDownload, QrArt, type PocketDownloadProps }\n",
      "type": "registry:component",
      "target": "@components/ballmac/templates/pocket/pocket-download.tsx"
    },
    {
      "path": "registry/ballmac/app/pocket/page.tsx",
      "content": "// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket\nimport type { Metadata } from \"next\"\n\nimport { PocketHome } from \"@/components/ballmac/templates/pocket/pocket-home\"\n\nexport const metadata: Metadata = {\n  title: \"Pocket: money that keeps up\",\n  description: \"One app for spending, saving and splitting. No fees to open or to leave.\",\n}\n\nexport default function Page() {\n  return <PocketHome />\n}\n",
      "type": "registry:page",
      "target": "app/pocket/page.tsx"
    },
    {
      "path": "registry/ballmac/app/pocket/features/page.tsx",
      "content": "// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket\nimport type { Metadata } from \"next\"\n\nimport { PocketFeatures } from \"@/components/ballmac/templates/pocket/pocket-features\"\n\nexport const metadata: Metadata = {\n  title: \"Features · Pocket\",\n  description: \"Freeze a card, tune round-ups, split a bill and convert money, live.\",\n}\n\nexport default function Page() {\n  return <PocketFeatures />\n}\n",
      "type": "registry:page",
      "target": "app/pocket/features/page.tsx"
    },
    {
      "path": "registry/ballmac/app/pocket/pricing/page.tsx",
      "content": "// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket\nimport type { Metadata } from \"next\"\n\nimport { PocketPricing } from \"@/components/ballmac/templates/pocket/pocket-pricing\"\n\nexport const metadata: Metadata = {\n  title: \"Pricing · Pocket\",\n  description: \"Free forever, with Plus and Metal for extras.\",\n}\n\nexport default function Page() {\n  return <PocketPricing />\n}\n",
      "type": "registry:page",
      "target": "app/pocket/pricing/page.tsx"
    },
    {
      "path": "registry/ballmac/app/pocket/security/page.tsx",
      "content": "// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket\nimport type { Metadata } from \"next\"\n\nimport { PocketSecurity } from \"@/components/ballmac/templates/pocket/pocket-security\"\n\nexport const metadata: Metadata = {\n  title: \"Security · Pocket\",\n  description: \"How Pocket keeps your money safe, and what happens if you lose your phone.\",\n}\n\nexport default function Page() {\n  return <PocketSecurity />\n}\n",
      "type": "registry:page",
      "target": "app/pocket/security/page.tsx"
    },
    {
      "path": "registry/ballmac/app/pocket/download/page.tsx",
      "content": "// Ballmac UI: Pocket template route. https://ui.ballmac.com/templates/template-pocket\nimport type { Metadata } from \"next\"\n\nimport { PocketDownload } from \"@/components/ballmac/templates/pocket/pocket-download\"\n\nexport const metadata: Metadata = {\n  title: \"Download · Pocket\",\n  description: \"Free on iPhone and Android.\",\n}\n\nexport default function Page() {\n  return <PocketDownload />\n}\n",
      "type": "registry:page",
      "target": "app/pocket/download/page.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "template",
      "mobile app",
      "fintech",
      "landing",
      "pricing",
      "phone",
      "download"
    ],
    "version": "1.0.0",
    "updated": "2026-10-01",
    "ai": {
      "summary": "Installs a five-page mobile-app landing site with a working app in a phone frame, live feature demos, pricing with a yearly toggle, a security page and a download page. Edit pocket-data.ts and pocketCss.",
      "whenToUse": [
        "Mobile app and fintech landing sites",
        "Any product that benefits from a live demo inside a phone"
      ],
      "whenNotToUse": [
        "Real banking flows (this is marketing; connect your own auth and APIs)"
      ],
      "composesWith": [
        "phone-frame",
        "switch",
        "slider"
      ],
      "a11y": [
        {
          "keys": "Bottom tab bar in the phone",
          "action": "Arrow-free tabs: Tab to a button and press Enter to switch screens"
        },
        {
          "keys": "Freeze card switch",
          "action": "Space toggles it; a polite status message confirms the state"
        },
        {
          "keys": "Round-up slider",
          "action": "Arrow keys change monthly spending; the result is announced"
        }
      ],
      "customization": [
        "Replace plans, comparison rows and FAQ in pocket-data.ts",
        "Rebuild the screens inside PocketApp",
        "Edit pocketCss for the mint, cobalt and lime palette",
        "Replace QrArt with a real QR code"
      ]
    },
    "examples": [
      "template-pocket-demo",
      "template-pocket-features",
      "template-pocket-pricing",
      "template-pocket-security",
      "template-pocket-download"
    ],
    "url": "https://ui.ballmac.com/components/template-pocket"
  },
  "docs": "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.",
  "categories": [
    "templates"
  ],
  "type": "registry:block"
}