Tweak copy and add links

This commit is contained in:
jwinterm
2026-06-01 11:10:31 -04:00
parent 4b2ae5646c
commit 254e969c36
7 changed files with 165 additions and 167 deletions
@@ -44,7 +44,7 @@ export const FounderSignature = () => {
He previously co-founded <span className="text-foreground font-semibold">Patrn LLC</span> (art101.io), a series of art-history NFT drops, and <span className="text-foreground font-semibold">Tabby Labs</span>, which was developing a cryptocurrency wallet with an interactive world inside.
</p>
<p className="text-muted-foreground leading-relaxed mt-4">
He most recently taught engineering at <span className="text-foreground font-semibold">Cecil College</span> and senior-level materials engineering (microfabrication, nanomaterials) at <span className="text-foreground font-semibold">Frostburg State University</span>. Active in cryptocurrency since 2014; <a href="https://github.com/jwinterm" target="_blank" rel="noopener noreferrer" className="text-foreground font-semibold underline decoration-primary/50 hover:text-primary transition-colors">GitHub</a> for the receipts.
He most recently taught engineering at <span className="text-foreground font-semibold">Cecil College</span> and senior-level materials engineering (microfabrication, nanomaterials) at <span className="text-foreground font-semibold">Frostburg State University</span>. Active in cryptocurrency since 2014, with a public track record on <a href="https://github.com/jwinterm" target="_blank" rel="noopener noreferrer" className="text-foreground font-semibold underline decoration-primary/50 hover:text-primary transition-colors">GitHub</a>.
</p>
</div>
</div>
@@ -2,103 +2,97 @@ import { Card } from "@repo/ui/components/card";
import Image from "next/image";
import Link from "next/link";
// Literal class strings per color so Tailwind's JIT keeps them (no dynamic interpolation).
const cardBg: Record<string, string> = {
orange: "!bg-orange-50/95 dark:!bg-orange-950/95 !border-orange-500/20",
yellow: "!bg-yellow-50/95 dark:!bg-yellow-950/95 !border-yellow-500/20",
amber: "!bg-amber-50/95 dark:!bg-amber-950/95 !border-amber-500/20",
emerald: "!bg-emerald-50/95 dark:!bg-emerald-950/95 !border-emerald-500/20",
blue: "!bg-blue-50/95 dark:!bg-blue-950/95 !border-blue-500/20",
green: "!bg-green-50/95 dark:!bg-green-950/95 !border-green-500/20",
};
const titleColor: Record<string, string> = {
orange: "text-orange-700 dark:text-orange-400",
yellow: "text-yellow-700 dark:text-yellow-400",
amber: "text-amber-700 dark:text-amber-400",
emerald: "text-emerald-700 dark:text-emerald-400",
blue: "text-blue-700 dark:text-blue-400",
green: "text-green-700 dark:text-green-400",
};
const imgBorder: Record<string, string> = {
orange: "border-orange-500/10",
yellow: "border-yellow-500/10",
amber: "border-amber-500/10",
emerald: "border-emerald-500/10",
blue: "border-blue-500/10",
green: "border-green-500/10",
};
const spanClass: Record<number, string> = {
1: "md:col-span-1",
2: "md:col-span-2",
};
type Item = {
name: string;
tagline: string;
color: keyof typeof titleColor;
span: 1 | 2;
image: string;
alt: string;
href: string;
external?: boolean;
};
// Order matters: spans 2,1,1,2,2,1 tile a 3-column grid with no gaps while alternating the
// wide side row to row for a balanced bento look.
const items: Item[] = [
{ name: "Wownerogue", tagline: "Provably-fair roguelike, synced to crypto block times.", color: "orange", span: 2, image: "/images/products/privacy-labs.png", alt: "Screenshot of the Wownerogue roguelike dungeon-crawler", href: "/products/wownerogue" },
{ name: "Neroswap", tagline: "DEX & CEX orderbook aggregator.", color: "yellow", span: 1, image: "/images/products/neroswap.png", alt: "Screenshot of the Neroswap orderbook aggregator", href: "https://neroswap.com", external: true },
{ name: "Smirk Wallet", tagline: "Non-custodial browser wallet with social tipping.", color: "amber", span: 1, image: "/images/products/smirk-wallet.png", alt: "Smirk Wallet browser extension", href: "https://smirk.cash", external: true },
{ name: "Occupy Wallets", tagline: "Custom e-commerce storefront we build and host for an art brand.", color: "emerald", span: 2, image: "/images/products/occupy-wallets.png", alt: "Occupy Wallets online store and gallery", href: "https://occupywallets.art", external: true },
{ name: "Bauhaus Echo", tagline: "Visual memory puzzle game.", color: "blue", span: 2, image: "/images/products/bauhaus-echo.png", alt: "Bauhaus Echo visual memory puzzle game", href: "/products/bauhaus-echo" },
{ name: "Vegan IQ", tagline: "Plant-based trivia game.", color: "green", span: 1, image: "/images/products/vegan-iq.png", alt: "Vegan IQ plant-based trivia game", href: "/products/vegan-iq" },
];
function BentoCard({ item, delay }: { item: Item; delay: number }) {
const inner = (
<Card className={`h-full glass-card group min-h-[300px] rounded-[2.5rem] ${cardBg[item.color]} cursor-pointer`}>
<div className="absolute inset-x-0 top-0 z-20 p-6 bg-gradient-to-b from-background/95 to-transparent pointer-events-none">
<h3 className={`text-xl font-bold ${titleColor[item.color]}`}>{item.name}</h3>
<p className="text-sm mt-1 text-foreground font-semibold">{item.tagline}</p>
</div>
<div className={`absolute inset-x-4 bottom-4 top-24 rounded-lg overflow-hidden z-10 bg-black/5 dark:bg-white/5 border ${imgBorder[item.color]} shadow-inner`}>
<Image
src={item.image}
alt={item.alt}
fill
className="object-contain p-2 opacity-60 transition-transform duration-1000 group-hover:scale-105"
sizes={item.span === 2 ? "(max-width: 768px) 100vw, 66vw" : "(max-width: 768px) 100vw, 33vw"}
/>
</div>
</Card>
);
const className = `bento-item ${spanClass[item.span]}`;
const style = { animationDelay: `${delay}ms` };
return item.external ? (
<a href={item.href} target="_blank" rel="noopener noreferrer" className={className} style={style}>
{inner}
</a>
) : (
<Link href={item.href} className={className} style={style}>
{inner}
</Link>
);
}
export const PortfolioGrid = () => {
return (
<section className="grid grid-cols-1 md:grid-cols-4 auto-rows-[300px] gap-6 w-full max-w-7xl mx-auto p-4 z-10 relative">
{/* Row 1: Wownerogue (2x1) */}
<Link href="/products/wownerogue" className="bento-item md:col-span-2" style={{ animationDelay: "0ms" }}>
<Card className="h-full glass-card group min-h-[300px] rounded-[2.5rem] !bg-orange-50/95 dark:!bg-orange-950/95 !border-orange-500/20 cursor-pointer">
<div className="absolute inset-x-0 top-0 z-20 p-6 bg-gradient-to-b from-background/95 to-transparent pointer-events-none">
<h3 className="text-xl font-bold text-orange-700 dark:text-orange-400">Wownerogue</h3>
<p className="text-sm mt-1 text-foreground font-semibold">Provably-fair multiplayer roguelike, synced to Monero and Wownero blocks.</p>
</div>
<div className="absolute inset-x-4 bottom-4 top-24 rounded-lg overflow-hidden z-10 bg-black/5 dark:bg-white/5 border border-orange-500/10 shadow-inner">
<Image
src="/images/products/privacy-labs.png"
alt="Screenshot of the Wownerogue and Monerogue roguelike dungeon-crawler game"
fill
className="object-contain p-2 opacity-60 transition-transform duration-1000 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
</Card>
</Link>
{/* Row 1: Smirk Wallet (2x1) */}
<Link href="https://smirk.cash" target="_blank" rel="noopener noreferrer" className="bento-item md:col-span-2" style={{ animationDelay: "75ms" }}>
<Card className="h-full glass-card group min-h-[300px] rounded-[2.5rem] !bg-amber-50/95 dark:!bg-amber-950/95 !border-amber-500/20 cursor-pointer">
<div className="absolute inset-x-0 top-0 z-20 p-6 bg-gradient-to-b from-background/95 to-transparent pointer-events-none">
<h3 className="text-xl font-bold text-amber-700 dark:text-amber-400">Smirk Wallet</h3>
<p className="text-sm mt-1 text-foreground font-semibold">Non-custodial browser wallet with encrypted social tipping.</p>
</div>
<div className="absolute inset-x-4 bottom-4 top-24 rounded-lg overflow-hidden z-10 bg-black/5 dark:bg-white/5 border border-amber-500/10 shadow-inner flex items-center justify-center">
<Image
src="/images/products/smirk-wallet.png"
alt="Screenshot of Smirk Wallet browser extension showing multi-currency support for BTC, LTC, XMR, WOW, and GRIN"
fill
className="object-contain p-4 opacity-60 transition-transform duration-1000 group-hover:scale-110"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
</Card>
</Link>
{/* Row 2: Neroswap (2x1) */}
<Link href="https://neroswap.com" target="_blank" rel="noopener noreferrer" className="bento-item md:col-span-2" style={{ animationDelay: "150ms" }}>
<Card className="h-full glass-card group min-h-[300px] rounded-[2.5rem] !bg-yellow-50/95 dark:!bg-yellow-950/95 !border-yellow-500/20 cursor-pointer">
<div className="absolute inset-x-0 top-0 z-20 p-6 bg-gradient-to-b from-background/95 to-transparent pointer-events-none">
<h3 className="text-xl font-bold text-yellow-700 dark:text-yellow-400">Neroswap</h3>
<p className="text-sm mt-1 text-foreground font-semibold">DEX &amp; CEX orderbook aggregator.</p>
</div>
<div className="absolute inset-x-4 bottom-4 top-24 rounded-lg overflow-hidden z-10 bg-black/5 dark:bg-white/5 border border-yellow-500/10 shadow-inner">
<Image
src="/images/products/neroswap.png"
alt="Screenshot of Neroswap DEX and CEX orderbook aggregator interface"
fill
className="object-cover opacity-50 transition-transform duration-1000 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
</Card>
</Link>
{/* Row 2: Bauhaus Echo (1x1) */}
<Link href="/products/bauhaus-echo" className="bento-item md:col-span-1" style={{ animationDelay: "225ms" }}>
<Card className="h-full glass-card group min-h-[300px] rounded-[2.5rem] !bg-blue-50/95 dark:!bg-blue-950/95 !border-blue-500/20 cursor-pointer">
<div className="absolute inset-x-0 top-0 z-20 p-6 bg-gradient-to-b from-background/95 to-transparent pointer-events-none">
<h3 className="text-xl font-bold text-blue-700 dark:text-blue-400">Bauhaus Echo</h3>
<p className="text-sm mt-1 text-foreground font-semibold">Visual memory puzzle game.</p>
</div>
<div className="absolute inset-x-4 bottom-4 top-24 rounded-lg overflow-hidden z-10 bg-black/5 dark:bg-white/5 border border-blue-500/10 shadow-inner">
<Image
src="/images/products/bauhaus-echo.png"
alt="Screenshot of Bauhaus Echo visual memory puzzle game with geometric tiles"
fill
className="object-contain p-2 opacity-50 transition-transform duration-1000 group-hover:scale-110"
sizes="(max-width: 768px) 100vw, 25vw"
/>
</div>
</Card>
</Link>
{/* Row 2: Occupy Wallets (1x1) */}
<Link href="https://occupywallets.art" target="_blank" rel="noopener noreferrer" className="bento-item md:col-span-1" style={{ animationDelay: "300ms" }}>
<Card className="h-full glass-card group min-h-[300px] rounded-[2.5rem] cursor-pointer">
<div className="absolute inset-0 z-20 p-6 flex flex-col justify-center items-center text-center pointer-events-none">
<h3 className="text-2xl font-bold text-zinc-900 dark:text-white drop-shadow-sm bg-white/60 dark:bg-black/60 backdrop-blur-3xl rounded-xl px-6 py-2">Occupy Wallets</h3>
<p className="text-zinc-900 dark:text-zinc-200 font-bold drop-shadow-sm bg-white/60 dark:bg-black/60 backdrop-blur-3xl rounded-xl px-4 py-2 mt-4 text-sm">High-fidelity gallery for fiscal graffiti.</p>
</div>
<div className="absolute inset-4 rounded-xl overflow-hidden z-10 bg-zinc-200/50 dark:bg-zinc-800/50">
<Image
src="/images/products/occupy-wallets.png"
alt="Screenshot of Occupy Wallets gallery displaying illustrated artwork with political and economic commentary"
fill
className="object-contain p-4 opacity-60 transition-transform duration-1000 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, 25vw"
/>
</div>
</Card>
</Link>
<section className="grid grid-cols-1 md:grid-cols-3 auto-rows-[300px] gap-6 w-full max-w-7xl mx-auto p-4 z-10 relative">
{items.map((item, i) => (
<BentoCard key={item.name} item={item} delay={i * 75} />
))}
</section>
);
};
+2 -4
View File
@@ -72,13 +72,11 @@ export function SuchoiceStoreButtons() {
}
export function SuchMoonLaunchStoreButtons() {
// Both stores submitted 2026-05-18; pending review. Flip null → real URLs
// once the app is live (Apple assigns the appstore.com /id<NUM> at first
// approval; Google URL is predictable as id=com.suchsoftware.suchmoonlaunch).
// Google Play is live; Apple still in review (flip null → real URL once approved).
return (
<StoreButtons
links={[
{ platform: "google", href: null },
{ platform: "google", href: "https://play.google.com/store/apps/details?id=com.suchsoftware.suchmoonlaunch" },
{ platform: "apple", href: null },
]}
extraLinks={[