/** * CyberLux storefront catalog — in-universe listings (see site footer for real-world status). * * Images: each SKU gets a stable Unsplash URL via `resolveProductImage` (hashed by id). * To use your own file: put it in `public/shop-assets/` and set `assetFile: "my-photo.webp"` on that SKU. */ import { sellerIdForProduct } from "@/lib/shopSellers"; export type ShopCurrency = "BTC" | "ETH" | "USD" | "XMR"; export type ShopProduct = { id: string; name: string; description: string; price: number; currency: ShopCurrency; category: string; /** Assigned in SHOP_PRODUCTS from sellerIdForProduct — stable per SKU */ sellerId: string; limited?: boolean; glowColor?: string; /** Drop a file at public/shop-assets/{assetFile} to override the remote image */ assetFile?: string; }; /** Unsplash photo paths — royalty-free hotlink; rotate by product id */ const UNSPLASH_ROTATOR = [ "photo-1563013544-824ae1b704d3", "photo-1553062407-98eeb64c6a62", "photo-1523275335684-37898b6baf30", "photo-1505740420928-5e560c06d30e", "photo-1542291026-7eec264c27ff", "photo-1526170375885-4d8ecf77b99f", "photo-1518544801979-152483f7e79e", "photo-1550751827-4bd374c3f58b", "photo-1618005188914-3c8315f33e6f", "photo-1558618047-3c8c76ca7d13", "photo-1551288049-bebda4e38f71", "photo-1635070041078-e363dbe005cb", "photo-1517694712202-14dd9538aa97", "photo-1526374965328-7f61d4dc18c5", "photo-1555949963-aa79dcee981c", "photo-1614854262312-209b1c0b2c7b", "photo-1592503254549-83d24b4fc4a6", "photo-1593359677876-a0bb1c3a8095", "photo-1611162616305-c69b3fa7fbe0", "photo-1581091226825-a6a2a5aee158", "photo-1518770660439-4636190af475", "photo-1460925895917-afdab827c52f", "photo-1451187580459-43490279c0fa", "photo-1582719478250-c89cae4dc85b", "photo-1559757148-5c350d0d3c56", "photo-1584433144859-1fc3ab64a54f", "photo-1512941937669-90a1b58e7e9c", "photo-1605812860427-4024433a70fd", "photo-1563986768609-322da13575f3", "photo-1639762681485-074b7f938ba0", ] as const; function hashId(id: string): number { let h = 0; for (let i = 0; i < id.length; i++) h = (h + id.charCodeAt(i) * (i + 1)) % 2147483647; return Math.abs(h); } /** Remote image URL (internet) or your file under public/shop-assets/ */ export function resolveProductImage(p: ShopProduct): string { if (p.assetFile?.trim()) { return `/shop-assets/${p.assetFile.replace(/^\/+/, "")}`; } const idx = hashId(p.id) % UNSPLASH_ROTATOR.length; const path = UNSPLASH_ROTATOR[idx]!; return `https://images.unsplash.com/${path}?w=800&q=85&auto=format&fit=crop`; } const GLOWS = [ "neon-cyan", "neon-purple", "neon-pink", "neon-green", "neon-yellow", "neon-red", "neon-blue", ] as const; type Seed = Omit & { id?: string }; type ProductDraft = Omit; function block(category: string, items: Seed[]): ProductDraft[] { return items.map((raw, j) => { const id = raw.id ?? `${category.slice(0, 3)}-${hashId(`${category}-${raw.name}-${j}`).toString(36)}`; const { id: _drop, ...rest } = raw; return { id, glowColor: GLOWS[hashId(id) % GLOWS.length], ...rest, category, }; }); } /** Everything offered in the shop — expand by adding more `block(...)` rows */ const ALL_BLOCKS: ProductDraft[] = [ ...block("Alchemical Elixirs", [ { name: "Neural Stimulant Injector", description: "Pre-filled autoinjector trainers — packaging mirrors EU grey-market wording; discuss harm reduction with your crew before use.", price: 0.085, currency: "BTC", limited: true }, { name: "Cognitive patch kit (12h)", description: "Transdermal placebo narrative for discussing FDA vs grey-market copy.", price: 0.019, currency: "XMR" }, { name: "Synaptic dampener v2", description: "Plot device for ‘too much focus’ cyberpunk arcs — pure chrome.", price: 0.042, currency: "ETH" }, { name: "RNA mimic cream (theatrical)", description: "Salon-grade tub with aggressive RNA branding — parse the ingredient deck before you trust the claims.", price: 124, currency: "USD" }, { name: "Dream-state diffuser oil", description: "Diffuser blend marketed for lucid downtime — ships as 30ml amber bottle, COA on request.", price: 0.007, currency: "BTC" }, { name: "Circadian hijack glasses", description: "Blue-shift fable hardware — compare to real sleep science slides.", price: 0.011, currency: "ETH" }, { name: "Quad-core adrenaline tabs", description: "Press-fit tabs, stim-forward copy — contraindicated if you run hot BP; novelty packaging only where law allows.", price: 0.003, currency: "BTC" }, { name: "Empathy rollback serum", description: "Satirical item naming — discuss manipulation in vendor prose.", price: 0.028, currency: "XMR", limited: true }, { name: "Vagus nerve tickler wand", description: "Machined aluminum grip, wellness-grade marketing — verify medical claims independently.", price: 89, currency: "USD" }, { name: "Mitochondria vanity stack", description: "Stacks-Sigma meme inventory for listing trust workshops.", price: 0.015, currency: "ETH" }, { name: "CRISPR cosplay pipette set", description: "Plastic props only; lab safety tangent.", price: 0.008, currency: "BTC" }, { name: "Nano-lattice bandage roll", description: "Tactical-wrap roll with lattice weave claims — IFAK-adjacent staging prop.", price: 0.031, currency: "XMR" }, { name: "Hormone whisperer lozenges", description: "Wild claims section — annotate red flags.", price: 42, currency: "USD" }, { name: "Deep-sleep coffin pod (mini)", description: "Showpiece prop; ergonomics vs marketing photos.", price: 1.12, currency: "BTC", limited: true }, { name: "Bio-firewall nasal gel", description: "Saline-forward gel marketed as ‘bio-firewall’ — novelty wellness SKU with aggressive copy.", price: 0.006, currency: "ETH" }, ]), ...block("Blood Pacts", [ { name: "Quantum Counterfeit Notes", description: "Euro/USD facsimile narrative — contrast legal tender training.", price: 1.25, currency: "ETH", limited: true }, { name: "Quantum‑Forged Euros brick", description: "UV-reactive novelty brick facsimile — training prop for banknote exam teams.", price: 2.4, currency: "BTC" }, { name: "Wash-trade tutorial ledger", description: "Ledger skinsheet pack demonstrating wash arcs — compliance training desks only.", price: 350, currency: "USD" }, { name: "Tornado nostalgia mixer tile", description: "Ceramic coaster etched with retro tumbler motif — office lore for chain-hopping traders.", price: 0.018, currency: "XMR" }, { name: "Bearer bond hologram folio", description: "Hologram theatre for verifying embossing vs phishing scans.", price: 0.055, currency: "BTC" }, { name: "Flash-loan bedtime story PDF", description: "Illustrated DeFi risk fable — onboarding gift for desk traders; watermarked PDF drop.", price: 0.002, currency: "ETH" }, { name: "OTC desk stress toy", description: "Squeeze toy shaped like a bid/ask spread arrow.", price: 19, currency: "USD" }, { name: "Ponzi pyramid desk lamp", description: "Conversation starter for MLM vs crypto scams.", price: 0.009, currency: "BTC" }, { name: "ISO-4217 mood ring set", description: "Currency-code jewelry — macroeconomics icebreaker.", price: 0.014, currency: "ETH" }, { name: "Dark-pool goggles (UV)", description: "UV-party wraparounds with liquidity-pool etch — con-floor flex piece.", price: 76, currency: "USD" }, { name: "Satoshi séance board", description: "Ouija-but-for-txids gag merch for history-of-Bitcoin week.", price: 0.022, currency: "XMR" }, { name: "Rug-pull rip cord keychain", description: "Pull cord plays airhorn.wav — memes in risk lectures.", price: 12, currency: "USD" }, { name: "Synthetic stablecoin snow globe", description: "Glitter settles ‘slowly’ — talk peg mechanics.", price: 0.033, currency: "ETH" }, { name: "Wire-instructions rubber stamp", description: "Rubber stamp of a phishing wire template — redact exercise.", price: 28, currency: "USD" }, { name: "Credit-default swap aromatherapy", description: "Scented candles named after 2008 instruments — dark humor.", price: 0.004, currency: "BTC" }, ]), ...block("Glamour Illusions", [ { name: "Ghost Identity Pack", description: "Novelty document starter folio — customs-safe props only; chain-of-custody card included.", price: 3.8, currency: "BTC", limited: true }, { name: "Burner SSN bingo card", description: "Bingo of invalid patterns; teaches checksum thinking.", price: 0.012, currency: "ETH" }, { name: "Deepfake voice coupon (fake)", description: "Coupon promising cloned voice — discuss consent frameworks.", price: 54, currency: "USD" }, { name: "Rubber face mesh MVP", description: "Theatrical mask — biometrics vs presentation attack discussion.", price: 0.19, currency: "XMR" }, { name: "Nom de guerre generator dial", description: "Spinner toy producing alias suggestions — OPSEC naming.", price: 22, currency: "USD" }, { name: "PGP key birthday card", description: "Paper card with mini public key block — party trick.", price: 0.005, currency: "BTC" }, { name: "SIM-swap panic button (prop)", description: "Big red prop — carrier escalation roleplay.", price: 15, currency: "USD" }, { name: "Synthetic genealogy tome", description: "Fake family tree book for social-engineering awareness.", price: 0.041, currency: "ETH" }, { name: "Iris-print latte art stencil", description: "Coffee stencil of an iris — biometrics humor.", price: 9, currency: "USD" }, { name: "Deadname incinerator USB shell", description: "Empty USB case labeled dramatically — data hygiene talk.", price: 0.017, currency: "XMR" }, { name: "Notary cosplay embosser", description: "Manual embosser with comic sans seal — trust UX jokes.", price: 31, currency: "USD" }, { name: "Ghost resume parchment", description: "Aged paper stock for redacted CV workshop.", price: 0.008, currency: "BTC" }, { name: "Witness protection hoodie", description: "Blank hoodie with detachable name tag — anonymity chat.", price: 0.024, currency: "ETH" }, { name: "Forged signature practice pad", description: "Legal-only handwriting exercise pad — anti-fraud angle.", price: 17, currency: "USD" }, ]), ...block("Ward Enchantments", [ { name: "Zero‑Day Exploit Kit (sandbox)", description: "Lab-only PoC bundle narrative — legal use disclaimers printed on sleeve.", price: 12.5, currency: "ETH", limited: true }, { name: "Darknet VPN Router", description: "Hardware VLAN folklore; compare to real router hardening checklists.", price: 0.5, currency: "XMR" }, { name: "Air-gapped Faraday lunchbox", description: "Metal mesh tin for phones — teaches Faraday basics.", price: 44, currency: "USD" }, { name: "EDR evasion board game", description: "Roll dice to patch telemetry — tabletop IR prep.", price: 0.026, currency: "BTC" }, { name: "Tor-shaped stress squishy", description: "Slow-rise foam onion — desk lounge swag for relay operators.", price: 11, currency: "USD" }, { name: "Memory-safe tea cozy", description: "Knitted cozy labeled ‘no buffer overflows here’.", price: 0.013, currency: "ETH" }, { name: "ROP-chain friendship bracelet", description: "Stainless charms stamped with gadget glyphs — wear-stack for con-floor insiders.", price: 7, currency: "USD" }, { name: "Purple-team piñata", description: "Filled with paper ‘findings’ slips — team-building prop.", price: 33, currency: "USD" }, { name: "Canary token confetti cannon", description: "Party cannon shoots paper canary strings — debut alerting.", price: 0.021, currency: "XMR" }, { name: "SIEM-themed scented candle", description: "Smells like ‘log rotation’ — joke SKU for SOC night shift.", price: 18, currency: "USD" }, { name: "Firewall prayer candle", description: "Saints of iptables — discuss faith vs config management.", price: 0.004, currency: "BTC" }, { name: "Quantum-safe bumper sticker", description: "Bumper sticker pack hyping PQC migration timelines.", price: 0.009, currency: "ETH" }, { name: "Bug-bounty bingo night kit", description: "Cards with OWASP categories — socialize triage vocabulary.", price: 26, currency: "USD" }, { name: "Yubikey trench coat lining", description: "Sew-in loops for 12 keys — physical key mgmt humor.", price: 0.038, currency: "BTC" }, { name: "Password-spray supersoaker (empty)", description: "Bright plastic supersoaker — discuss rate limits metaphorically.", price: 14, currency: "USD" }, { name: "Red-team nerf darts (foam)", description: "Foam darts tagged ‘lateral movement’ — safe play fights.", price: 0.006, currency: "XMR" }, ]), ...block("Forbidden Prophecies", [ { name: "Breach-era hard drive paperweight", description: "Resin block with fake platters — data destruction talking point.", price: 0.016, currency: "BTC" }, { name: "CSV of emotions (parody)", description: "Joke spreadsheet about feelings — privacy vs oversharing.", price: 3, currency: "USD" }, { name: "Anonymized pet photos dataset", description: "Synthetic dog shots, metadata-stripped tarball — ML sandbox starter.", price: 0.011, currency: "ETH" }, { name: "Pastebin snowshoes", description: "Foam snowshoes with ‘expiring URL’ stickers — opsec metaphor.", price: 55, currency: "USD" }, { name: "Doxxing dodgeball (foam)", description: "Foam stress ball stenciled PII — conference giveaway for privacy talks.", price: 12, currency: "USD" }, { name: "Hash-slinging souvenir spatula", description: "Kitchen spatula etched with SHA-256 joke.", price: 0.007, currency: "BTC" }, { name: "Journalists’ USB condom charm", description: "Tiny rubber USB blocker on keyring — supply-chain hygiene.", price: 8, currency: "USD" }, { name: "DLC for older leaks (empty case)", description: "Empty steel case promising ‘expansion packs’ — hype satire.", price: 0.029, currency: "XMR" }, { name: "Redaction marker stadium pack", description: "Black markers labeled for FOIA fantasy workshops.", price: 19, currency: "USD" }, { name: "Telemetry piñata (no network)", description: "Offline piñata with paper ‘events’ — logging trivia.", price: 27, currency: "USD" }, { name: "GDPR meditation tape", description: "Cassette of white noise labeled ‘right to be forgotten’.", price: 0.005, currency: "ETH" }, { name: "Metadata shedding lint roller", description: "Gag lint roller ‘removes EXIF’ — teach real exiftool after.", price: 6, currency: "USD" }, { name: "Leak-themed escape room clue pack", description: "Chain-of-custody puzzle cards for escape-room operators — sealed deck.", price: 0.02, currency: "BTC" }, { name: "Ransom note magnetic poetry", description: "Fridge magnets of cliché ransom phrases — decrypt jokes.", price: 15, currency: "USD" }, ]), ...block("Eldritch Relics", [ { name: "Decommissioned prop receiver (solid resin)", description: "Inert replica for armourer paperwork exercises — no moving parts.", price: 0.32, currency: "XMR", limited: true }, { name: "Orange-tip training carbine (airsoft)", description: "Clear plastic training piece — jurisdiction checklist included.", price: 199, currency: "USD" }, { name: "Ballistic gel dessert mold", description: "Silicone mold shaped like gel block — baking + terminal ballistics pun.", price: 24, currency: "USD" }, { name: "Blade geometry slide rule", description: "Plastic slide rule for grind angles — metallurgy intro.", price: 0.014, currency: "ETH" }, { name: "Non-firing museum rack mount", description: "Wall mount for decommissioned props — discuss secure storage law.", price: 48, currency: "USD" }, { name: "Rubber training bayonet", description: "Soft bayonet for stage combat class.", price: 32, currency: "USD" }, { name: "Blueprints wall art (demil)", description: "Poster schematics with ‘demilled’ watermark — ITAR conversation.", price: 0.018, currency: "BTC" }, { name: "Snap-cap choir set", description: "Harmless snap caps for chorus-line dry-fire drills (supervised).", price: 41, currency: "USD" }, { name: "Range officer clipboard folio", description: "Clipboard with safety checklist prompts.", price: 17, currency: "USD" }, { name: "Kevlar-thread friendship bracelet", description: "Braided accent band — marketing references aramid; tensile spec on vendor sheet.", price: 0.009, currency: "XMR" }, ]), ...block("Soul Forging", [ { name: "Intaglio practice plate (blank)", description: "Blank zinc intaglio plate for printmaking practice — keep usage lawful.", price: 67, currency: "USD" }, { name: "UV counterfeit reveal postcard set", description: "Postcards with hidden UV layers — doc verification labs.", price: 0.012, currency: "BTC" }, { name: "Microprint magnifier chain", description: "Jeweler loupe necklace — inspect fine printing legitimately.", price: 21, currency: "USD" }, { name: "Hologram sticker starter pack", description: "generic shiny stickers — compare to banknote holograms.", price: 0.008, currency: "ETH" }, { name: "Passport photo booth curtain (prop)", description: "Curtain fabric roll for mock booth setup.", price: 56, currency: "USD" }, { name: "Raised-seal cosplay wax sticks", description: "Assorted wax sticks for hobby embossing — not for government documents.", price: 13, currency: "USD" }, { name: "Typography-of-banknotes poster", description: "Serif anatomy poster for design-history class.", price: 0.015, currency: "XMR" }, { name: "Frank Abagnale movie night kit", description: "Popcorn + discussion guide — fraud history framed responsibly.", price: 9, currency: "USD" }, { name: "Watermark cotton paper sampler", description: "Sampler pack of cotton bond — conservation chemistry tangent.", price: 34, currency: "USD" }, { name: "Forgery panic flowchart scroll", description: "Wall scroll for ‘if you find a fake, then…’ decisions.", price: 0.006, currency: "BTC" }, { name: "Embossing press desk toy", description: "Desktop lever press for foil hobby work — keep off official parchment.", price: 88, currency: "USD" }, { name: "Counterfeit color-match Pantone joke book", description: "Parody swatch book — teach perceptual tricks.", price: 0.022, currency: "ETH" }, { name: "Notarization rubber duck", description: "Duck with stamp hat — debug your trust assumptions.", price: 5, currency: "USD" }, ]), ...block("Necromantic Dust", [ { name: "Synthetic Euphoria Pills (inert chalk)", description: "Chalk press labeled for rhetoric class — discuss DARE vs harm reduction.", price: 0.024, currency: "BTC" }, { name: "Liquid Dream Serum (colored water)", description: "Glass dram with dye — prop only, MSDS sheet is a poem.", price: 0.18, currency: "XMR", limited: true }, { name: "Round-bottom flask stress orb", description: "Squishy flask — lab safety mascot.", price: 10, currency: "USD" }, { name: "Periodic table shower curtain", description: "Actually useful chemistry dorm decor.", price: 29, currency: "USD" }, { name: "Nitrogen dewar shot glass (steel)", description: "Steel mini cup shaped like dewar — LN₂ jokes, not included.", price: 0.011, currency: "ETH" }, { name: "Fume hood sash height sticker pack", description: "Vinyl stickers reminding sash position — lab tours.", price: 7, currency: "USD" }, { name: "GHS pictogram cookie cutters", description: "Bake hazard-symbol cookies — safety comms.", price: 16, currency: "USD" }, { name: "Precursor-themed spice labels (joke)", description: "Labels for cumin jar saying ‘not a precursor’ — legal humor.", price: 0.004, currency: "BTC" }, { name: "Affinity chromatography plush column", description: "Stuffed toy shaped like a column — biochem softness.", price: 37, currency: "USD" }, { name: "CRC Handbook coaster set", description: "Coasters printed with fake constants — trivia nights.", price: 0.019, currency: "XMR" }, { name: "Ampoule snap practice kit (sugar)", description: "Sugar ampoules for snapping motion drills — no glass cuts.", price: 23, currency: "USD" }, { name: "Titration mood light", description: "Lamp that shifts color like pH — aesthetics of indicators.", price: 44, currency: "USD" }, { name: "Beaker creature plush", description: "Monster made of stacked beakers — PPE still required.", price: 0.013, currency: "ETH" }, { name: "Lab notebook with waterproof lies", description: "Notebook advertising ‘indestructible claims’ — epistemology gag.", price: 18, currency: "USD" }, ]), ...block("Fey Offerings", [ { name: "Blue Raspberry Bubblegum brick", description: "Bulk gum for candy-market grid — sticker claims ‘encrypted flavor’.", price: 0.002, currency: "BTC" }, { name: "Sour Watermelon wedge bag", description: "Sour belts in Mylar — discuss packaging OPSEC as metaphor.", price: 0.0015, currency: "BTC" }, { name: "Mystery Mix Cryptobag", description: "Assorted odds; QR on label resolves to nutrition facts PDF.", price: 0.005, currency: "BTC", limited: true }, { name: "Glow-in-the-Dark Taffy rope", description: "UV-reactive taffy for blacklight display case only.", price: 0.003, currency: "ETH" }, { name: "Tor onion gummy mold", description: "Silicone mold shaped like Tor logo onions — make gummies legally.", price: 14, currency: "USD" }, { name: "Monero-mint chocolate bar", description: "Dark-mint bar in foil printed with ring-sig artwork — ships cold-packed.", price: 0.007, currency: "XMR" }, { name: "Hash-brownie mix (literal potato)", description: "Potato hash brown mix — pun SKU for blockchain week.", price: 8, currency: "USD" }, { name: "PGP-signed lollipop", description: "Lollipop with wrapper showing fake ASCII armor — unwrap carefully.", price: 0.004, currency: "BTC" }, { name: "Dead-drop jawbreaker", description: "Layers of color like nested containers — tradecraft candy metaphor.", price: 6, currency: "USD" }, { name: "Honey-pot honey jar", description: "Real jar of honey labeled honeypot — Infosec picnic.", price: 17, currency: "USD" }, { name: "Zero-knowledge nougat", description: "Nougat bar claiming ‘you taste it but can’t prove it’ — ZKP joke.", price: 0.006, currency: "ETH" }, { name: "Bitcoin-orange rock candy geode", description: "Rock candy geode dyed BTC orange — geology + crypto pun.", price: 11, currency: "USD" }, { name: "Cold-storage ice pop molds", description: "Popsicle molds shaped like hardware wallets — summer syllabus.", price: 13, currency: "USD" }, { name: "Mixer-themed cotton candy floss sugar", description: "Pastel sugars labeled hop1/hop2/hop3 — sweet talk about mixers.", price: 20, currency: "USD" }, ]), ...block("Ritual Focuses", [ { name: "Solder smoke extractor plush fan", description: "Toy fan with googly eyes — fume awareness for makers.", price: 36, currency: "USD" }, { name: "JTAG duck debugger", description: "Rubber duck with labeled test points — hardware RE humor.", price: 0.017, currency: "BTC" }, { name: "TPM tamper-evident sticker sheet", description: "Destructive void labels for chassis sealing — audits love these.", price: 12, currency: "USD" }, { name: "Flipper Zero cosplay foam", description: "Foam replica — discuss responsible RF rules.", price: 0.01, currency: "ETH" }, { name: "Airgap Ethernet cable (sewn shut)", description: "Cable sewn closed — literal air gap joke.", price: 9, currency: "USD" }, { name: "SD-card sorting tray", description: "3D-print tray for forensic imaging class prop sorting.", price: 25, currency: "USD" }, { name: "Logic analyzer hair clip (prop)", description: "Hair clip shaped like LA probes — signal integrity vibes.", price: 7, currency: "USD" }, { name: "Raspberry Pi oven mitt", description: "Oven mitt with GPIO pinout print — kitchen cluster jokes.", price: 18, currency: "USD" }, { name: "KVM switch fidget cube", description: "Cube with tiny clicky KVM toggles — focus toy for admins.", price: 0.014, currency: "XMR" }, { name: "PDU power-strip storybook", description: "Kids book about not overloading circuits — datacenter bedtime.", price: 15, currency: "USD" }, ]), ...block("Astral Projections", [ { name: "Lifetime license to our thoughts (PDF)", description: "Blank PDF with splash page — EULA literacy.", price: 0.001, currency: "ETH" }, { name: "NFT of this paragraph (screenshot)", description: "PNG screenshot — discuss provenance vs possession.", price: 0.008, currency: "BTC" }, { name: "Vaporware roadmap deck template", description: "Keynote template full of vague quarters.", price: 5, currency: "USD" }, { name: "SaaS subscription to nothing", description: "Stripe-looking receipt for $0/mo — dark patterns talk.", price: 0, currency: "USD" }, { name: "Cracked screen wallpaper pack", description: "PNG wallpapers — social engineering bait awareness.", price: 3, currency: "USD" }, { name: "ISO27001 compliance cat video", description: "MP4 of cat knocking audit binder off desk.", price: 0.003, currency: "XMR" }, { name: "Phishing email mad-libs HTML", description: "Template with blanks for grammar of scams.", price: 0.006, currency: "BTC" }, { name: "API rate-limit lullaby MP3", description: "Lo-fi beats for waiting on 429 responses.", price: 7, currency: "USD" }, { name: "Kubernetes yaml horoscope", description: "Text files mapping star signs to misconfig jokes.", price: 0.004, currency: "ETH" }, { name: "Dark-mode-only whitepaper (empty)", description: "White PDF named ironically — accessibility tangent.", price: 2, currency: "USD" }, ]), ...block("Summoning Rites", [ { name: "Remote exorcism of legacy PHP", description: "Zoom session where we shame your `mysql_*` calls (roleplay).", price: 0.09, currency: "BTC" }, { name: "Tarot for TLS certificate expiry", description: "Performative reading of cert timelines — automate after.", price: 45, currency: "USD" }, { name: "On-site donut-driven threat modeling", description: "Bring donuts, draw stride threats on napkins.", price: 120, currency: "USD" }, { name: "ASMR packet capture whisper stream", description: "1hr ambient `.pcap` readout — sleep for nerds.", price: 0.016, currency: "XMR" }, { name: "Corporate values alignment séance", description: "Parody workshop aligning ‘synergy’ with firewall rules.", price: 0.027, currency: "ETH" }, { name: "Retrospective on your retrospective", description: "Facilitator block booking — billed in 0.25 agile-day increments.", price: 88, currency: "USD" }, { name: "Perl poetry code review", description: "Critique of badly written haiku in Perl — nostalgia service.", price: 0.012, currency: "BTC" }, { name: "Blockchain-of-custody bakery pickup", description: "We sign a paper chain while you pick up muffins.", price: 35, currency: "USD" }, ]), ]; function dedupeById(products: ProductDraft[]): ProductDraft[] { const seen = new Set(); const out: ProductDraft[] = []; for (const p of products) { if (seen.has(p.id)) continue; seen.add(p.id); out.push(p); } return out; } export const SHOP_PRODUCTS: ShopProduct[] = dedupeById(ALL_BLOCKS).map((p) => ({ ...p, sellerId: sellerIdForProduct(p.id), })); export function shopProductsForSeller(sellerId: string): ShopProduct[] { return SHOP_PRODUCTS.filter((p) => p.sellerId === sellerId); } export const SHOP_PRODUCT_COUNT = SHOP_PRODUCTS.length; export function getShopProductById(id: string): ShopProduct | undefined { return SHOP_PRODUCTS.find((p) => p.id === id); } export function shopCategoryCounts(): { name: string; count: number; icon: string }[] { const icons: Record = { "Alchemical Elixirs": "🧪", "Blood Pacts": "🩸", "Glamour Illusions": "🎭", "Ward Enchantments": "🛡️", "Forbidden Prophecies": "📜", "Eldritch Relics": "🗡️", "Soul Forging": "⚒️", "Necromantic Dust": "⚱️", "Fey Offerings": "🍄", "Ritual Focuses": "🔮", "Astral Projections": "✨", "Summoning Rites": "🕯️", }; const m = new Map(); for (const p of SHOP_PRODUCTS) { m.set(p.category, (m.get(p.category) ?? 0) + 1); } return [...m.entries()] .map(([name, count]) => ({ name, count, icon: icons[name] ?? "⬡" })) .sort((a, b) => a.name.localeCompare(b.name)); } export function featuredShopProducts(n = 8): ShopProduct[] { return [...SHOP_PRODUCTS].sort((a, b) => (b.limited ? 1 : 0) - (a.limited ? 1 : 0) || hashId(a.id) - hashId(b.id)).slice(0, n); }