Harden onion boot flow and deepen site surfaces

Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation.

Made-with: Cursor
This commit is contained in:
drjones
2026-04-07 21:35:52 -07:00
parent 52432dccfa
commit 78a071ba02
162 changed files with 21692 additions and 39 deletions

View File

@@ -0,0 +1,119 @@
"use client";
import { useMemo } from "react";
import { SHOP_PRODUCTS, shopCategoryCounts, type ShopCurrency } from "@/lib/shopCatalog";
function currencySymbol(c: ShopCurrency): string {
if (c === "BTC") return "₿";
if (c === "ETH") return "Ξ";
if (c === "XMR") return "⏣";
return "$";
}
export default function MarketAnalyticsPage() {
const { byCategory, byCurrency, avgPriceUsdish, limitedCount } = useMemo(() => {
const cats = shopCategoryCounts();
const cur: Record<ShopCurrency, number> = { BTC: 0, ETH: 0, USD: 0, XMR: 0 };
let usdSum = 0;
let n = 0;
let lim = 0;
for (const p of SHOP_PRODUCTS) {
cur[p.currency]++;
if (p.currency === "USD") {
usdSum += p.price;
n++;
} else if (p.currency === "BTC") {
usdSum += p.price * 65_000;
n++;
} else if (p.currency === "ETH") {
usdSum += p.price * 3_500;
n++;
} else {
usdSum += p.price * 165;
n++;
}
if (p.limited) lim++;
}
const maxCat = Math.max(1, ...cats.map((c) => c.count));
const maxCur = Math.max(1, ...Object.values(cur));
return {
byCategory: cats.map((c) => ({ ...c, pct: Math.round((c.count / maxCat) * 100) })),
byCurrency: (Object.entries(cur) as [ShopCurrency, number][]).map(([k, v]) => ({
k,
v,
pct: Math.round((v / maxCur) * 100),
})),
avgPriceUsdish: n ? usdSum / n : 0,
limitedCount: lim,
};
}, []);
return (
<div className="space-y-10 font-mono text-[#c8ffd8]">
<header>
<p className="text-[10px] uppercase tracking-[0.45em] text-[#00ff41]/45">Layer 2 · floor telemetry</p>
<h1 className="mt-2 text-2xl font-black tracking-tight text-[#7af598] md:text-3xl">Analytics</h1>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-[#5a8f6a]">
Derived from the live catalog in <code className="text-[#7af598]">shopCatalog</code> not a third-party charting plugin. Bars are CSS; numbers update when SKUs change. Use this view to explain category heat and currency mix on vendor calls or mirror status pages.
</p>
</header>
<section className="grid gap-6 md:grid-cols-3">
<div className="rounded border border-[#00ff41]/25 bg-[#050a08]/90 p-5">
<p className="text-[10px] uppercase tracking-widest text-[#00ff41]/50">SKUs</p>
<p className="mt-1 text-3xl font-black text-[#b4ffcc]">{SHOP_PRODUCTS.length}</p>
</div>
<div className="rounded border border-[#00ff41]/25 bg-[#050a08]/90 p-5">
<p className="text-[10px] uppercase tracking-widest text-[#00ff41]/50">Limited drops</p>
<p className="mt-1 text-3xl font-black text-[#ff9a9a]">{limitedCount}</p>
</div>
<div className="rounded border border-[#00ff41]/25 bg-[#050a08]/90 p-5">
<p className="text-[10px] uppercase tracking-widest text-[#00ff41]/50">Avg notional (rough USD)</p>
<p className="mt-1 text-3xl font-black text-[#7af598]">
${avgPriceUsdish.toFixed(0)}
</p>
<p className="mt-2 text-[9px] text-[#4a6b55]">BTC/ETH/XMR converted with static fiction rates for display only.</p>
</div>
</section>
<section className="rounded border border-[#00ff41]/20 p-6">
<h2 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/70">Category mix</h2>
<ul className="mt-4 space-y-3">
{byCategory.map((c) => (
<li key={c.name} className="flex items-center gap-3 text-xs">
<span className="w-8 shrink-0 text-lg">{c.icon}</span>
<span className="w-36 shrink-0 font-bold text-[#b4ffcc]">{c.name}</span>
<div className="h-2 min-w-0 flex-1 overflow-hidden rounded bg-[#0a120d]">
<div className="h-full bg-gradient-to-r from-[#00ff41]/20 to-[#7af598]" style={{ width: `${c.pct}%` }} />
</div>
<span className="w-10 shrink-0 text-right text-[#6a9b7a]">{c.count}</span>
</li>
))}
</ul>
</section>
<aside className="rounded border border-dashed border-[#00ff41]/25 p-4 text-[10px] leading-relaxed text-[#4a6b55]">
<strong className="text-[#5a8f6a]">Telemetry vocabulary:</strong> heat is relative SKU density per category, mix is currency tag share, notional is a
fiction USD bridge using static BTC/ETH/XMR anchors useful for comparing stalls, not for pricing legal tender. All terms index the{" "}
<strong className="text-[#6a9b7a]">Void crawler</strong> when mirrored on search-enabled onions.
</aside>
<section className="rounded border border-[#00ff41]/20 p-6">
<h2 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/70">Currency mix</h2>
<ul className="mt-4 space-y-3">
{byCurrency.map(({ k, v, pct }) => (
<li key={k} className="flex items-center gap-3 text-xs">
<span className="w-10 shrink-0 font-bold text-[#9dffc4]">
{currencySymbol(k)} {k}
</span>
<div className="h-2 min-w-0 flex-1 overflow-hidden rounded bg-[#0a120d]">
<div className="h-full bg-[#00ff41]/35" style={{ width: `${pct}%` }} />
</div>
<span className="w-10 shrink-0 text-right text-[#6a9b7a]">{v}</span>
</li>
))}
</ul>
</section>
</div>
);
}

97
app/market/intel/page.tsx Normal file
View File

@@ -0,0 +1,97 @@
import Link from "next/link";
export default function MarketIntelPage() {
return (
<div className="space-y-10 font-mono text-[#c8ffd8]">
<header>
<p className="text-[10px] uppercase tracking-[0.45em] text-[#00ff41]/45">Layer 3 · vetting</p>
<h1 className="mt-2 text-2xl font-black tracking-tight text-[#7af598] md:text-3xl">Buyer intelligence</h1>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-[#5a8f6a]">
A deep market needs a deep threat model. This page is the in-universe briefing buyers read before large orders: how to read stall telemetry, when to walk away, and how CyberLux surfaces risk without turning the UI into nagware.
</p>
</header>
<section className="rounded border border-[#00ff41]/20 p-6">
<h2 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/70">Stall signals (what the UI already shows)</h2>
<div className="mt-4 overflow-x-auto">
<table className="w-full border-collapse text-left text-xs text-[#7ab896]">
<thead>
<tr className="border-b border-[#00ff41]/20 text-[10px] uppercase tracking-wider text-[#00ff41]/50">
<th className="py-2 pr-4">Signal</th>
<th className="py-2 pr-4">Healthy</th>
<th className="py-2">Caution</th>
</tr>
</thead>
<tbody className="divide-y divide-[#00ff41]/10">
<tr>
<td className="py-3 font-bold text-[#b4ffcc]">Rating trajectory</td>
<td>Stable over 90d window</td>
<td>Sudden jump after mass low-value sales</td>
</tr>
<tr>
<td className="py-3 font-bold text-[#b4ffcc]">Review velocity</td>
<td>Matches order volume in analytics band</td>
<td>Spike of one-liners, no verified purchases</td>
</tr>
<tr>
<td className="py-3 font-bold text-[#b4ffcc]">PGP history</td>
<td>Chained rotations with signed notices</td>
<td>Fresh key + aggressive discounting</td>
</tr>
<tr>
<td className="py-3 font-bold text-[#b4ffcc]">Category fit</td>
<td>Listings match stated specialty</td>
<td>Random SKU sprawl outside bond tier</td>
</tr>
</tbody>
</table>
</div>
</section>
<section className="grid gap-6 md:grid-cols-2">
<div className="rounded border border-dashed border-[#ff6b6b]/35 bg-[#1a0808]/40 p-5">
<h3 className="text-xs font-black uppercase tracking-widest text-[#ff9a9a]">Hard stops</h3>
<ul className="mt-3 list-disc space-y-2 pl-4 text-xs text-[#c9a0a0]">
<li>Vendor asks to finalize off-platform to save fees.</li>
<li>Mirror URL not present in your signed bundle.</li>
<li>Checkout address differs from last verified fingerprint without a signed rotation.</li>
</ul>
</div>
<div className="rounded border border-[#00ff41]/20 p-5">
<h3 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/70">Soft signals</h3>
<ul className="mt-3 list-disc space-y-2 pl-4 text-xs text-[#6a9b7a]">
<li>New stall with perfect photos request timestamped proof.</li>
<li>SKU copies another listing verbatim possible scraper.</li>
<li>Shipping region mismatch vs vendor claimed locale.</li>
</ul>
</div>
</section>
<section className="rounded border border-[#00ff41]/15 p-6 text-xs leading-relaxed text-[#6a9b7a]">
<h2 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/60">Narrative environment</h2>
<p className="mt-3">
Buyers should assume <strong className="text-[#b4ffcc]">Sybil stalls</strong>, <strong className="text-[#b4ffcc]">liquidity ghosts</strong>, and{" "}
<strong className="text-[#b4ffcc]">mirror drift</strong> until a signed bundle says otherwise. The floor encourages{" "}
<strong className="text-[#b4ffcc]">compartmentalized handles</strong>, <strong className="text-[#b4ffcc]">burner sessions</strong>, and{" "}
<strong className="text-[#b4ffcc]">jurisdiction-agnostic shipping fiction</strong> so Tor latency and packet jitter do not get mistaken for vendor
incompetence. When in doubt, cross-read <strong className="text-[#b4ffcc]">forum rings</strong> for stall drama before large commits.
</p>
</section>
<p className="text-[10px] text-[#4a6b55]">
Cross-links:{" "}
<Link href="/market/analytics" className="text-[#7af598] hover:underline">
Floor analytics
</Link>
{" · "}
<Link href="/search" className="text-[#7af598] hover:underline">
Crawler
</Link>
{" · "}
<Link href="/forum" className="text-[#7af598] hover:underline">
Forum rings
</Link>
</p>
</div>
);
}

5
app/market/layout.tsx Normal file
View File

@@ -0,0 +1,5 @@
import MarketSiteChrome from "@/components/market/MarketSiteChrome";
export default function MarketLayout({ children }: { children: React.ReactNode }) {
return <MarketSiteChrome>{children}</MarketSiteChrome>;
}

View File

@@ -0,0 +1,102 @@
import Link from "next/link";
export default function MarketOperationsPage() {
return (
<div className="space-y-10 font-mono text-[#c8ffd8]">
<header>
<p className="text-[10px] uppercase tracking-[0.45em] text-[#00ff41]/45">Layer 2 · fulfillment stack</p>
<h1 className="mt-2 text-2xl font-black tracking-tight text-[#7af598] md:text-3xl">Operations &amp; pipeline</h1>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-[#5a8f6a]">
The market is not a static directory. Every SKU routes through a staged pipeline: intake, bond, listing QA, buyer messaging, ship window, and dispute arbitration. Below is how CyberLux models that stack in software so mirrors and onions stay coherent even when traffic splits across forty-three hidden services.
</p>
</header>
<section className="rounded border border-[#00ff41]/25 bg-[#050a08]/90 p-6 md:p-8">
<h2 className="border-b border-[#00ff41]/15 pb-2 text-sm font-black uppercase tracking-widest text-[#9dffc4]">
Order state machine
</h2>
<ol className="mt-6 space-y-4 text-sm leading-relaxed text-[#7ab896]">
<li>
<strong className="text-[#b4ffcc]">Draft</strong> cart lines held client-side; no vendor notification until checkout commits a signed bundle.
</li>
<li>
<strong className="text-[#b4ffcc]">Committed</strong> checkout posts intent; escrow layer (see{" "}
<Link href="/market/trust" className="text-[#7af598] underline hover:text-white">
Trust
</Link>
) opens a cooling window for key verification.
</li>
<li>
<strong className="text-[#b4ffcc]">Vendor ack</strong> stall owner confirms stock and ship SLA; late ack downgrades stall priority in search ranking.
</li>
<li>
<strong className="text-[#b4ffcc]">In transit</strong> tracking tokens are opaque hashes; plaintext carriers never touch the hub.
</li>
<li>
<strong className="text-[#b4ffcc]">Settled / disputed</strong> auto-release after timeout unless a ticket opens a moderator queue tied to the same order id across all onions.
</li>
</ol>
</section>
<section className="grid gap-6 md:grid-cols-2">
<div className="rounded border border-[#00ff41]/20 p-6">
<h3 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/70">SLA tiers (in-world)</h3>
<ul className="mt-4 space-y-3 text-xs leading-relaxed text-[#6a9b7a]">
<li>
<span className="font-bold text-[#9dffc4]">Standard:</span> vendor ack within 48h simulated clock; ship within 120h.
</li>
<li>
<span className="font-bold text-[#9dffc4]">Express bond:</span> higher vendor bond unlocks 12h ack and pinned placement in category rails.
</li>
<li>
<span className="font-bold text-[#9dffc4]">Cold chain / sensitive:</span> extra QA step before listing goes live; edits re-trigger QA.
</li>
</ul>
</div>
<div className="rounded border border-[#00ff41]/20 p-6">
<h3 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/70">Dispute ladder</h3>
<ol className="mt-4 list-decimal space-y-2 pl-4 text-xs leading-relaxed text-[#6a9b7a]">
<li>Buyer vendor thread (PGP-signed).</li>
<li>Floor mediator binds to listing category expertise.</li>
<li>Market council multi-sig release or partial refund.</li>
<li>Permanent ban + bond forfeit for pattern fraud.</li>
</ol>
</div>
</section>
<section className="rounded border border-dashed border-[#00ff41]/30 p-6 text-xs leading-relaxed text-[#4a6b55]">
<strong className="text-[#6a9b7a]">Why this page exists:</strong> dedicated Tor onions for <code className="text-[#7af598]">/market</code> should feel like a full vertical, not a shallow iframe. The pipeline text mirrors how cart, checkout, and support routes are wired in the Next app so operators can explain the same story on any mirror.
</section>
<section className="rounded border border-[#00ff41]/20 bg-[#030806]/80 p-6 md:p-8">
<h2 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/65">Glossary · ops vocabulary</h2>
<dl className="mt-4 grid gap-4 text-xs text-[#6a9b7a] md:grid-cols-2">
<div>
<dt className="font-bold text-[#9dffc4]">Signed bundle</dt>
<dd className="mt-1 leading-relaxed">
Mirror list + hub fingerprint + timestamp; clients verify before trusting checkout addresses or vendor rotations across rendezvous points.
</dd>
</div>
<div>
<dt className="font-bold text-[#9dffc4]">Opaque hash</dt>
<dd className="mt-1 leading-relaxed">
Tracking token that maps to carrier events only inside vendor tooling plaintext courier names never cross the Next boundary.
</dd>
</div>
<div>
<dt className="font-bold text-[#9dffc4]">Cooling window</dt>
<dd className="mt-1 leading-relaxed">
Post-commit interval where buyers validate PGP continuity and multisig cosigners can abort without burning reputation.
</dd>
</div>
<div>
<dt className="font-bold text-[#9dffc4]">Category rail</dt>
<dd className="mt-1 leading-relaxed">
Faceted slice of the catalog used for pinned placement; express-bond stalls can lease rail time without polluting unrelated SKUs.
</dd>
</div>
</dl>
</section>
</div>
);
}

185
app/market/page.tsx Normal file
View File

@@ -0,0 +1,185 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { useMemo, useState } from "react";
import { useSearchParams } from "next/navigation";
import { ProductSocialBlock } from "@/components/shop/ProductSocialBlock";
import { useCart } from "@/contexts/CartContext";
import {
SHOP_PRODUCT_COUNT,
SHOP_PRODUCTS,
resolveProductImage,
shopCategoryCounts,
type ShopCurrency,
type ShopProduct,
} from "@/lib/shopCatalog";
import { getProductSocialMetrics } from "@/lib/shopProductSocial";
import { SHOP_SELLER_COUNT, getSellerById } from "@/lib/shopSellers";
function formatPrice(price: number, currency: ShopCurrency): string {
if (currency === "BTC") return price.toFixed(6);
if (currency === "ETH") return price.toFixed(4);
if (currency === "XMR") return price.toFixed(3);
return price.toFixed(2);
}
const SYM: Record<ShopCurrency, string> = {
BTC: "₿",
ETH: "Ξ",
USD: "$",
XMR: "⏣",
};
export default function MarketPage() {
const sp = useSearchParams();
const initialCat = sp.get("category") ?? "";
const [q, setQ] = useState("");
const [category, setCategory] = useState(initialCat);
const facet = useMemo(() => shopCategoryCounts(), []);
const filtered = useMemo(() => {
const ql = q.trim().toLowerCase();
const tokens = ql.split(/\s+/).filter(Boolean);
return SHOP_PRODUCTS.filter((p) => {
if (category && p.category !== category) return false;
if (tokens.length === 0) return true;
const seller = getSellerById(p.sellerId);
const sellerHay = seller ? `${seller.handle} ${seller.bio} ${seller.specialty}` : "";
const hay = `${p.name} ${p.description} ${p.category} ${p.id} ${sellerHay}`.toLowerCase();
return tokens.every((t) => hay.includes(t));
});
}, [q, category]);
return (
<div className="font-mono text-[#00ff41]">
<section className="mb-8 border-b border-[#00ff41]/20 pb-6">
<p className="text-[10px] uppercase tracking-[0.4em] text-[#00ff41]/50">Layer 1 · live floor</p>
<p className="mt-2 max-w-3xl text-sm text-[#00ff41]/65">
<strong className="text-[#7af598]">{SHOP_PRODUCT_COUNT}</strong> SKUs ·{" "}
<Link href="/vendors" className="font-bold text-[#9dffc4] underline hover:text-white">
{SHOP_SELLER_COUNT} vendor stalls
</Link>
per-listing reviews, velocity, and cart handoff into checkout (USD estimate from spot). Use the left rail for ops, trust, and intel layers.
</p>
</section>
<div className="mb-6 flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
<div className="flex-1">
<label className="text-[10px] uppercase tracking-widest text-[#00ff41]/50">Search catalog</label>
<input
value={q}
onChange={(e) => setQ(e.target.value)}
placeholder="tokens match title, description, category…"
className="mt-1 w-full max-w-xl border-2 border-[#00ff41]/30 bg-black/80 px-4 py-3 text-sm text-[#c8ffd8] placeholder:text-[#00ff41]/25 focus:border-[#00ff41] focus:outline-none"
/>
</div>
<p className="text-xs text-[#00ff41]/50">
Showing <span className="text-[#7af598]">{filtered.length}</span> / {SHOP_PRODUCT_COUNT}
</p>
</div>
<div className="mb-8 flex flex-wrap gap-2">
<button
type="button"
onClick={() => setCategory("")}
className={`px-3 py-1.5 text-xs uppercase ${category === "" ? "bg-[#00ff41] text-black" : "border border-[#00ff41]/35 hover:bg-[#00ff41]/10"}`}
>
All
</button>
{facet.map((c) => (
<button
key={c.name}
type="button"
onClick={() => setCategory(c.name)}
className={`px-3 py-1.5 text-xs ${category === c.name ? "bg-[#00ff41] text-black" : "border border-[#00ff41]/35 hover:bg-[#00ff41]/10"}`}
>
<span className="mr-1">{c.icon}</span>
{c.name} ({c.count})
</button>
))}
</div>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
{filtered.map((p) => (
<MarketProductCard key={p.id} product={p} />
))}
</div>
{filtered.length === 0 ? (
<p className="mt-16 border border-dashed border-[#00ff41]/20 py-12 text-center text-sm text-[#00ff41]/50">
No SKUs match widen search or pick another category.
</p>
) : null}
</div>
);
}
function MarketProductCard({ product: p }: { product: ShopProduct }) {
const src = resolveProductImage(p);
const local = src.startsWith("/");
const v = getSellerById(p.sellerId);
const metrics = getProductSocialMetrics(p.id);
const { addToCart, hydrated } = useCart();
const [flash, setFlash] = useState(false);
return (
<article className="flex h-full flex-col border border-[#00ff41]/20 bg-[#0d0d0d] transition-all hover:border-[#00ff41]/55">
<div className="relative aspect-square w-full bg-black">
<Image
src={src}
alt=""
fill
className="object-cover"
sizes="(max-width: 640px) 100vw, (max-width: 1280px) 50vw, 25vw"
unoptimized={local}
/>
{p.limited ? (
<span className="absolute left-2 top-2 bg-[#ff00aa] px-2 py-0.5 text-[10px] font-bold uppercase text-black">Limited</span>
) : null}
</div>
<div className="flex flex-1 flex-col p-4">
<p className="text-[10px] uppercase tracking-wider text-[#00ff41]/45">{p.category}</p>
<h2 className="mt-1 text-base font-bold leading-snug text-[#d8ffe8]">{p.name}</h2>
<div className="mt-2 text-[#9dffc4]">
<ProductSocialBlock metrics={metrics} compact />
</div>
{v ? (
<p className="mt-2 text-[10px] text-[#00ff41]/55">
<span className="text-[#00ff41]/40">Seller</span>{" "}
<Link href={`/vendor/${v.slug}`} className="text-[#7af598] hover:text-white hover:underline">
{v.handle}
</Link>
<span className="text-[#00ff41]/35"> · stall {v.rating.toFixed(2)}</span>
</p>
) : null}
<p className="mt-2 line-clamp-3 text-xs leading-relaxed text-[#00ff41]/70">{p.description}</p>
<blockquote className="mt-3 border-l-2 border-[#00ff41]/30 pl-3 text-[11px] italic leading-snug text-[#b4ffcc]/80">
{metrics.testimonials[0]?.text}
<span className="mt-0.5 block font-mono text-[10px] not-italic text-[#00ff41]/45">
@{metrics.testimonials[0]?.handle} · {metrics.testimonials[0]?.daysAgo}d
</span>
</blockquote>
<div className="mt-4 flex flex-wrap items-center justify-between gap-2 border-t border-[#00ff41]/15 pt-3">
<span className="text-lg font-bold text-[#7af598]">
{SYM[p.currency]}
{formatPrice(p.price, p.currency)} <span className="text-xs font-normal text-[#00ff41]/50">{p.currency}</span>
</span>
<button
type="button"
disabled={!hydrated}
onClick={() => {
addToCart(p, 1);
setFlash(true);
window.setTimeout(() => setFlash(false), 1400);
}}
className="border border-[#00ff41] bg-[#00ff41] px-3 py-1.5 text-xs font-bold uppercase text-black hover:bg-[#7af598] disabled:opacity-50"
>
{flash ? "Added" : "Add"}
</button>
</div>
</div>
</article>
);
}

80
app/market/trust/page.tsx Normal file
View File

@@ -0,0 +1,80 @@
import Link from "next/link";
export default function MarketTrustPage() {
return (
<div className="space-y-10 font-mono text-[#c8ffd8]">
<header>
<p className="text-[10px] uppercase tracking-[0.45em] text-[#00ff41]/45">Layer 3 · settlement</p>
<h1 className="mt-2 text-2xl font-black tracking-tight text-[#7af598] md:text-3xl">Trust, escrow &amp; keys</h1>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-[#5a8f6a]">
Buyers should never wonder which plugin holds their funds. CyberLux treats trust as a layered contract: cryptographic identity first, timed release second, human arbitration last. Everything below is diegetic documentation for the storefront it aligns with how sessions, carts, and signed mirror lists behave in code.
</p>
</header>
<section className="space-y-4">
<h2 className="text-xs font-black uppercase tracking-[0.35em] text-[#00ff41]/55">Four trust layers</h2>
<div className="grid gap-4 md:grid-cols-2">
{[
{
n: "L1",
t: "Vendor bond",
d: "New stalls post collateral denominated in XMR/BTC fiction. Bond size gates category access (e.g. hardware vs digital).",
},
{
n: "L2",
t: "PGP continuity",
d: "Every listing shows a vendor fingerprint; checkout warns on mismatch. Rotations require signed announcements chained to the prior key.",
},
{
n: "L3",
t: "Timed escrow",
d: "Funds sit in a cooling state until ship proof + buyer silence or explicit release. Timeout paths are deterministic per SKU class.",
},
{
n: "L4",
t: "Council multisig",
d: "Escalations bind three moderators from disjoint rings; two-of-three releases or refunds with on-ledger rationale stubs.",
},
].map((x) => (
<article key={x.n} className="rounded border border-[#00ff41]/20 bg-[#040806]/80 p-5">
<span className="text-[10px] font-bold text-[#00ff41]/50">{x.n}</span>
<h3 className="mt-1 text-sm font-bold text-[#b4ffcc]">{x.t}</h3>
<p className="mt-2 text-xs leading-relaxed text-[#6a9b7a]">{x.d}</p>
</article>
))}
</div>
</section>
<section className="rounded border border-[#00ff41]/15 bg-[#040806]/90 p-6">
<h2 className="text-xs font-black uppercase tracking-widest text-[#00ff41]/60">Lexicon · settlement vocabulary</h2>
<p className="mt-3 text-xs leading-relaxed text-[#6a9b7a]">
<strong className="text-[#b4ffcc]">Watch-only wallet</strong> fiction for buyers who monitor UTXO flows without signing.{" "}
<strong className="text-[#b4ffcc]">Replace-by-fee</strong> mentioned only as a cautionary tale in checkout copy.{" "}
<strong className="text-[#b4ffcc]">Ring signatures</strong> referenced when explaining why Monero lanes default for privacy-marked SKUs.{" "}
<strong className="text-[#b4ffcc]">Airgapped signing</strong> for high-bond vendors rotating keys.{" "}
<strong className="text-[#b4ffcc]">Descriptor rotation</strong> ties vendor announcements to prior fingerprints so phishing clones stand out on any onion mirror.
</p>
</section>
<section className="rounded border border-[#00ff41]/25 p-6 md:p-8">
<h2 className="text-sm font-black uppercase tracking-widest text-[#9dffc4]">Key hygiene checklist</h2>
<ul className="mt-4 grid gap-3 text-xs leading-relaxed text-[#7ab896] md:grid-cols-2">
<li>Verify signed mirror bundles against the hub-published list before pasting addresses.</li>
<li>Never reuse a wallet label across stalls; phishing copies love reused nicknames.</li>
<li>Treat urgent finalization messages as untrusted until the order id matches your session.</li>
<li>Prefer XMR paths when the listing marks privacy-critical; BTC fiction still simulates fee spikes.</li>
</ul>
<p className="mt-6 text-[10px] uppercase tracking-wider text-[#00ff41]/40">
Related:{" "}
<Link href="/market/intel" className="text-[#7af598] hover:underline">
Buyer intel
</Link>
·{" "}
<Link href="/support" className="text-[#7af598] hover:underline">
Support ladder
</Link>
</p>
</section>
</div>
);
}