Files
volana/prototype/Volana.dc.html
2026-07-02 21:15:51 +02:00

1123 lines
80 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600;9..40,700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
:root {
--c-bg: #0e0e1c; --c-bg2: #13132a; --c-surf: #171730; --c-surf2: #1e1e3c;
--c-bd: #252548; --c-bd2: #323260;
--c-t: #ede9ff; --c-t2: #9b96c0; --c-t3: #605c88;
--c-a: #b060ff; --c-ad: rgba(176,96,255,.14); --c-ah: #9545e0;
--c-g: #14f195; --c-gd: rgba(20,241,149,.11);
--c-y: #f5a623; --c-yd: rgba(245,166,35,.11);
--c-r: #ff4d4f; --c-rd: rgba(255,77,79,.11);
--nav: rgba(14,14,28,.93);
}
[data-theme="light"] {
--c-bg: #f7f6fb; --c-bg2: #eeecfa; --c-surf: #ffffff; --c-surf2: #f0eef8;
--c-bd: #e2dff0; --c-bd2: #ccc8e8;
--c-t: #0b0b18; --c-t2: #5c5880; --c-t3: #9991b8;
--c-a: #7a34d4; --c-ad: rgba(122,52,212,.08); --c-ah: #6422b0;
--c-g: #059669; --c-gd: rgba(5,150,105,.08);
--c-y: #d97706; --c-yd: rgba(217,119,6,.08);
--c-r: #dc2626; --c-rd: rgba(220,38,38,.08);
--nav: rgba(247,246,251,.95);
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes fadeUp { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:translateY(0); } }
@keyframes slideIn { from { opacity:0; transform:translateX(16px); } to { opacity:1; transform:translateX(0); } }
input, button, select { font-family: inherit; }
button:focus-visible, input:focus-visible { outline: 2px solid var(--c-a); outline-offset: 2px; }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--c-bd2); border-radius: 3px; }
</style>
</helmet>
<div data-theme="{{ theme }}" style="min-height:100vh;background:var(--c-bg);color:var(--c-t);font-family:'DM Sans',system-ui,sans-serif;font-size:14px;">
<!-- ══════ NAV ══════ -->
<nav style="position:fixed;inset:0 0 auto;height:60px;background:var(--nav);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-bottom:1px solid var(--c-bd);z-index:100;">
<div style="max-width:1320px;margin:0 auto;height:100%;display:flex;align-items:center;gap:8px;padding:0 20px;">
<button onClick="{{ goHome }}" style="display:flex;align-items:center;gap:8px;background:none;border:none;cursor:pointer;padding:5px 8px;border-radius:8px;flex-shrink:0;" style-hover="background:var(--c-surf)">
<svg width="26" height="26" viewBox="0 0 26 26" fill="none"><rect width="26" height="26" rx="7" fill="var(--c-a)"/><path d="M6 9h14M6 13h9M6 17h11" stroke="white" stroke-width="2" stroke-linecap="round"/></svg>
<span style="font-size:16px;font-weight:700;letter-spacing:-0.4px;color:var(--c-t);">Volana</span>
</button>
<div style="flex:1;max-width:380px;position:relative;margin-left:6px;">
<svg style="position:absolute;left:10px;top:50%;transform:translateY(-50%);pointer-events:none;" width="14" height="14" viewBox="0 0 14 14"><circle cx="5.5" cy="5.5" r="4" stroke="var(--c-t3)" stroke-width="1.5" fill="none"/><path d="M9 9l3 3" stroke="var(--c-t3)" stroke-width="1.5" stroke-linecap="round"/></svg>
<input type="text" placeholder="Search listings…" value="{{ search }}" onChange="{{ onSearch }}" style="width:100%;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:8px;padding:7px 12px 7px 30px;font-size:13px;color:var(--c-t);"/>
</div>
<div style="flex:1;"></div>
<button onClick="{{ goBrowse }}" style="background:none;border:none;padding:7px 11px;border-radius:6px;font-size:13px;font-weight:500;color:var(--c-t2);cursor:pointer;" style-hover="color:var(--c-t);background:var(--c-surf)">Browse</button>
<sc-if value="{{ wallet }}" hint-placeholder-val="{{ false }}">
<button onClick="{{ goOrders }}" style="background:none;border:none;padding:7px 11px;border-radius:6px;font-size:13px;font-weight:500;color:var(--c-t2);cursor:pointer;" style-hover="color:var(--c-t);background:var(--c-surf)">My Orders</button>
</sc-if>
<div style="display:flex;align-items:center;gap:5px;padding:5px 10px;border-radius:6px;background:var(--c-surf);border:1px solid var(--c-bd);flex-shrink:0;">
<div style="width:6px;height:6px;border-radius:50%;background:var(--c-g);flex-shrink:0;"></div>
<span style="font-size:12px;font-weight:500;color:var(--c-t2);">Mainnet</span>
</div>
<button onClick="{{ toggleTheme }}" title="Toggle theme" style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:6px;width:32px;height:32px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0;" style-hover="border-color:var(--c-bd2)">{{ themeIcon }}</button>
<sc-if value="{{ notWallet }}" hint-placeholder-val="{{ true }}">
<button onClick="{{ openWalletModal }}" style="background:var(--c-a);color:#fff;border:none;border-radius:8px;padding:7px 15px;font-size:13px;font-weight:600;cursor:pointer;flex-shrink:0;white-space:nowrap;" style-hover="background:var(--c-ah)">Connect Wallet</button>
</sc-if>
<sc-if value="{{ wallet }}" hint-placeholder-val="{{ false }}">
<div style="position:relative;flex-shrink:0;">
<button onClick="{{ toggleWalletOpen }}" style="display:flex;align-items:center;gap:6px;background:var(--c-ad);border:1px solid var(--c-a);border-radius:8px;padding:6px 11px;cursor:pointer;" style-hover="background:var(--c-a)">
<div style="width:6px;height:6px;border-radius:50%;background:var(--c-g);flex-shrink:0;"></div>
<span style="font-size:12px;font-weight:600;color:var(--c-a);font-family:'DM Mono',monospace;letter-spacing:0.3px;">{{ addr }}</span>
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 4l3 3 3-3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
</button>
<sc-if value="{{ walletOpen }}" hint-placeholder-val="{{ false }}">
<div style="position:absolute;top:calc(100% + 6px);right:0;min-width:190px;background:var(--c-surf);border:1px solid var(--c-bd2);border-radius:10px;padding:8px;box-shadow:0 12px 40px rgba(0,0,0,.4);z-index:200;">
<div style="padding:6px 8px 10px;">
<div style="font-size:11px;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:4px;">Connected</div>
<div style="font-size:12px;color:var(--c-t);font-family:'DM Mono',monospace;">{{ addr }}</div>
</div>
<div style="height:1px;background:var(--c-bd);margin:0 -8px 6px;"></div>
<button onClick="{{ disconnectWallet }}" style="width:100%;background:none;border:none;padding:7px 8px;border-radius:6px;text-align:left;font-size:13px;color:var(--c-r);cursor:pointer;" style-hover="background:var(--c-rd)">Disconnect wallet</button>
</div>
</sc-if>
</div>
</sc-if>
</div>
</nav>
<!-- ══════ PAGES ══════ -->
<div style="padding-top:60px;min-height:calc(100vh - 60px);">
<!-- ── HOMEPAGE ── -->
<sc-if value="{{ showHome }}" hint-placeholder-val="{{ true }}">
<div style="animation:fadeUp .25s ease;">
<!-- HERO -->
<section style="min-height:calc(100vh - 60px);background:var(--c-bg);position:relative;display:flex;align-items:center;overflow:hidden;">
<div style="position:absolute;top:-280px;left:-150px;width:700px;height:700px;background:radial-gradient(circle,rgba(176,96,255,.11) 0%,transparent 65%);pointer-events:none;"></div>
<div style="position:absolute;bottom:-200px;right:50px;width:550px;height:550px;background:radial-gradient(circle,rgba(20,241,149,.055) 0%,transparent 65%);pointer-events:none;"></div>
<div style="max-width:1200px;margin:0 auto;padding:60px;display:grid;grid-template-columns:1fr 420px;gap:80px;align-items:center;width:100%;">
<!-- Headline -->
<div>
<div style="display:inline-flex;align-items:center;gap:8px;background:var(--c-gd);border:1px solid var(--c-g);border-radius:20px;padding:5px 14px;font-size:12px;font-weight:600;color:var(--c-g);margin-bottom:26px;">
<div style="width:6px;height:6px;border-radius:50%;background:var(--c-g);"></div>
Live on Solana Mainnet
</div>
<h1 style="font-size:62px;font-weight:800;letter-spacing:-2.5px;line-height:1.03;margin:0 0 20px;color:var(--c-t);">The marketplace<br/><span style="color:var(--c-a);">nobody controls.</span></h1>
<p style="font-size:17px;color:var(--c-t2);line-height:1.65;margin:0 0 34px;max-width:450px;">Buy and sell freely. Payments are final — no chargebacks, no frozen accounts. No government or corporation can remove a listing or block a transaction.</p>
<div style="display:flex;gap:12px;align-items:center;flex-wrap:wrap;">
<button onClick="{{ goBrowse }}" style="background:var(--c-a);color:#fff;border:none;border-radius:10px;padding:14px 28px;font-size:15px;font-weight:700;cursor:pointer;letter-spacing:-0.2px;" style-hover="background:var(--c-ah)">Browse Listings →</button>
<button style="background:none;border:1px solid var(--c-bd2);color:var(--c-t2);border-radius:10px;padding:14px 24px;font-size:15px;cursor:pointer;" style-hover="border-color:var(--c-t2);color:var(--c-t)">How it works ↓</button>
</div>
<div style="display:flex;gap:28px;margin-top:44px;padding-top:28px;border-top:1px solid var(--c-bd);">
<div><div style="font-size:22px;font-weight:700;color:var(--c-t);letter-spacing:-0.5px;">11</div><div style="font-size:11px;color:var(--c-t3);margin-top:2px;">Active listings</div></div>
<div><div style="font-size:22px;font-weight:700;color:var(--c-t);letter-spacing:-0.5px;">$24K+</div><div style="font-size:11px;color:var(--c-t3);margin-top:2px;">In escrow today</div></div>
<div><div style="font-size:22px;font-weight:700;color:var(--c-g);letter-spacing:-0.5px;">&lt;$0.001</div><div style="font-size:11px;color:var(--c-t3);margin-top:2px;">Per transaction</div></div>
</div>
</div>
<!-- Floating product card visual -->
<div style="position:relative;height:480px;">
<!-- Back card -->
<div style="position:absolute;top:60px;right:-10px;width:255px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:12px;overflow:hidden;transform:rotate(6deg);opacity:0.5;">
<div style="height:110px;background:#0e0820;display:flex;align-items:center;justify-content:center;font-size:40px;">🌐</div>
<div style="padding:12px 14px;">
<div style="font-size:12px;font-weight:600;color:var(--c-t);margin-bottom:5px;">myshop.sol Domain</div>
<div><span style="font-size:18px;font-weight:800;color:var(--c-a);">0.5</span><span style="font-size:11px;color:var(--c-t3);margin-left:3px;">SOL</span></div>
</div>
</div>
<!-- Main card -->
<div style="position:absolute;top:10px;left:0;width:275px;background:var(--c-surf);border:1px solid var(--c-bd2);border-radius:14px;overflow:hidden;box-shadow:0 40px 100px rgba(0,0,0,.55);transform:rotate(-2deg);">
<div style="height:155px;background:#0a1828;display:flex;align-items:center;justify-content:center;font-size:60px;position:relative;">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 35%,rgba(255,255,255,.07),transparent 60%);"></div>
<span style="position:relative;">💻</span>
</div>
<div style="padding:14px 16px;">
<div style="font-size:14px;font-weight:700;color:var(--c-t);margin-bottom:3px;letter-spacing:-0.2px;">MacBook Pro 14" M3 Pro</div>
<div style="font-size:11px;color:var(--c-t3);font-family:'DM Mono',monospace;margin-bottom:12px;">Gh9Z…mF8k · ⬡ Verified</div>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
<div><span style="font-size:24px;font-weight:800;color:var(--c-a);letter-spacing:-1px;">2.4</span><span style="font-size:12px;color:var(--c-t3);margin-left:3px;">SOL</span></div>
<span style="background:var(--c-gd);border:1px solid var(--c-g);color:var(--c-g);padding:2px 8px;border-radius:4px;font-size:10px;font-weight:600;">5 in stock</span>
</div>
<div style="background:var(--c-a);border-radius:7px;padding:9px;text-align:center;font-size:13px;font-weight:700;color:#fff;">Buy Now →</div>
</div>
</div>
<!-- Escrow badge -->
<div style="position:absolute;bottom:50px;right:0;background:var(--c-surf);border:1px solid var(--c-bd2);border-radius:10px;padding:10px 14px;box-shadow:0 8px 28px rgba(0,0,0,.4);">
<div style="font-size:10px;color:var(--c-t3);margin-bottom:3px;">Payment status</div>
<div style="font-size:12px;font-weight:600;color:var(--c-g);">✓ Locked in escrow</div>
</div>
<!-- On-chain badge -->
<div style="position:absolute;top:0;right:20px;background:var(--c-surf);border:1px solid var(--c-a);border-radius:8px;padding:6px 12px;">
<div style="font-size:11px;font-weight:600;color:var(--c-a);">⬡ On-chain verified</div>
</div>
</div>
</div>
</section>
<!-- WHY VOLANA -->
<section style="padding:80px 60px;border-top:1px solid var(--c-bd);">
<div style="max-width:1200px;margin:0 auto;">
<div style="text-align:center;margin-bottom:48px;">
<h2 style="font-size:38px;font-weight:700;letter-spacing:-1px;margin:0 0 10px;color:var(--c-t);">Rethinking the marketplace.</h2>
<p style="font-size:15px;color:var(--c-t2);max-width:460px;margin:0 auto;line-height:1.6;">Everything wrong with eBay, Amazon, and PayPal — fixed with open-source smart contracts.</p>
</div>
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px;">
<div style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:14px;padding:26px;">
<div style="width:40px;height:40px;border-radius:10px;background:var(--c-gd);border:1px solid var(--c-g);display:flex;align-items:center;justify-content:center;font-size:18px;margin-bottom:16px;"></div>
<div style="font-size:17px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.3px;">Final payments</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.65;margin-bottom:16px;">Once you confirm receipt, the payment is permanent. No chargebacks, no account freezes, no "we reversed your payment 6 months later."</div>
<div style="background:var(--c-surf2);border-radius:8px;padding:10px 12px;font-size:11px;color:var(--c-t3);">PayPal: chargebacks possible up to <span style="color:var(--c-r);font-weight:600;">180 days</span> after payment</div>
</div>
<div style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:14px;padding:26px;">
<div style="width:40px;height:40px;border-radius:10px;background:var(--c-ad);border:1px solid var(--c-a);display:flex;align-items:center;justify-content:center;font-size:18px;margin-bottom:16px;"></div>
<div style="font-size:17px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.3px;">Truly uncensorable</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.65;margin-bottom:16px;">No government, no company, no payment processor can remove a listing or block a purchase. The marketplace runs on open-source contracts on a public blockchain.</div>
<div style="background:var(--c-surf2);border-radius:8px;padding:10px 12px;font-size:11px;color:var(--c-t3);">eBay: listings removed without warning or appeal</div>
</div>
<div style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:14px;padding:26px;">
<div style="width:40px;height:40px;border-radius:10px;background:var(--c-yd);border:1px solid var(--c-y);display:flex;align-items:center;justify-content:center;font-size:18px;margin-bottom:16px;"></div>
<div style="font-size:17px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.3px;">Tiny fees</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.65;margin-bottom:16px;">Solana transactions cost fractions of a cent. No platform fee. Dispute mediator fees (0.51.5%) are only charged if a dispute is actually resolved.</div>
<div style="background:var(--c-surf2);border-radius:8px;padding:10px 12px;font-size:11px;color:var(--c-t3);">eBay + PayPal combined: up to <span style="color:var(--c-r);font-weight:600;">17%</span> per sale</div>
</div>
</div>
</div>
</section>
<!-- HOW IT WORKS -->
<section style="padding:80px 60px;border-top:1px solid var(--c-bd);background:var(--c-bg2);">
<div style="max-width:1200px;margin:0 auto;">
<div style="text-align:center;margin-bottom:52px;">
<h2 style="font-size:38px;font-weight:700;letter-spacing:-1px;margin:0 0 10px;color:var(--c-t);">How it works</h2>
<p style="font-size:15px;color:var(--c-t2);">Four steps. No account needed — just a Solana wallet.</p>
</div>
<div style="display:flex;align-items:flex-start;gap:0;">
<div style="flex:1;text-align:center;padding:0 20px;">
<div style="width:52px;height:52px;border-radius:50%;background:var(--c-ad);border:2px solid var(--c-a);display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:800;color:var(--c-a);margin:0 auto 16px;">1</div>
<div style="font-size:15px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.2px;">Browse</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.6;">Find what you want. Search, filter by currency, sort by price.</div>
</div>
<div style="padding-top:24px;color:var(--c-bd2);font-size:22px;flex-shrink:0;"></div>
<div style="flex:1;text-align:center;padding:0 20px;">
<div style="width:52px;height:52px;border-radius:50%;background:var(--c-surf);border:2px solid var(--c-bd2);display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:800;color:var(--c-t2);margin:0 auto 16px;">2</div>
<div style="font-size:15px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.2px;">Connect Wallet</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.6;">Connect Phantom, Solflare or Backpack. No email. No signup. No KYC.</div>
</div>
<div style="padding-top:24px;color:var(--c-bd2);font-size:22px;flex-shrink:0;"></div>
<div style="flex:1;text-align:center;padding:0 20px;">
<div style="width:52px;height:52px;border-radius:50%;background:var(--c-surf);border:2px solid var(--c-bd2);display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:800;color:var(--c-t2);margin:0 auto 16px;">3</div>
<div style="font-size:15px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.2px;">Confirm &amp; Escrow</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.6;">Approve in your wallet. Funds lock instantly into a tamper-proof on-chain escrow.</div>
</div>
<div style="padding-top:24px;color:var(--c-bd2);font-size:22px;flex-shrink:0;"></div>
<div style="flex:1;text-align:center;padding:0 20px;">
<div style="width:52px;height:52px;border-radius:50%;background:var(--c-surf);border:2px solid var(--c-bd2);display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:800;color:var(--c-t2);margin:0 auto 16px;">4</div>
<div style="font-size:15px;font-weight:700;color:var(--c-t);margin-bottom:8px;letter-spacing:-0.2px;">Receive &amp; Release</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.6;">Receive your goods, confirm receipt → seller gets paid. If anything goes wrong, your chosen mediator steps in.</div>
</div>
</div>
</div>
</section>
<!-- FEATURED LISTINGS -->
<section style="padding:72px 60px;border-top:1px solid var(--c-bd);">
<div style="max-width:1200px;margin:0 auto;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:24px;">
<h2 style="font-size:26px;font-weight:700;letter-spacing:-0.5px;margin:0;color:var(--c-t);">Featured listings</h2>
<button onClick="{{ goBrowse }}" style="background:none;border:1px solid var(--c-bd);color:var(--c-t2);border-radius:8px;padding:8px 16px;font-size:13px;cursor:pointer;" style-hover="border-color:var(--c-a);color:var(--c-a)">View all →</button>
</div>
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px;">
<sc-for list="{{ featuredProducts }}" as="fp" hint-placeholder-count="4">
<div onClick="{{ fp.clickCard }}" style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:10px;overflow:hidden;cursor:pointer;transition:transform .14s,border-color .14s;" style-hover="transform:translateY(-3px);border-color:var(--c-bd2);">
<div style="height:130px;background:{{ fp.bg }};display:flex;align-items:center;justify-content:center;font-size:48px;position:relative;">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 30%,rgba(255,255,255,.06),transparent 60%);"></div>
<span style="position:relative;">{{ fp.em }}</span>
</div>
<div style="padding:12px 13px;">
<div style="font-size:13px;font-weight:600;color:var(--c-t);line-height:1.3;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:7px;min-height:34px;">{{ fp.name }}</div>
<div><span style="font-size:18px;font-weight:800;color:var(--c-a);letter-spacing:-0.5px;">{{ fp.priceVal }}</span><span style="font-size:11px;color:var(--c-t3);margin-left:3px;">{{ fp.cur }}</span></div>
</div>
</div>
</sc-for>
</div>
</div>
</section>
<!-- BOTTOM CTA -->
<section style="padding:80px 60px;border-top:1px solid var(--c-bd);text-align:center;background:linear-gradient(160deg,var(--c-bg2) 0%,var(--c-bg) 100%);">
<div style="max-width:560px;margin:0 auto;">
<h2 style="font-size:38px;font-weight:800;letter-spacing:-1.5px;margin:0 0 14px;color:var(--c-t);">Ready to trade freely?</h2>
<p style="font-size:15px;color:var(--c-t2);line-height:1.65;margin:0 0 30px;">No account. No credit card. Just connect your wallet and start buying.</p>
<button onClick="{{ goBrowse }}" style="background:var(--c-a);color:#fff;border:none;border-radius:10px;padding:15px 36px;font-size:16px;font-weight:700;cursor:pointer;letter-spacing:-0.2px;" style-hover="background:var(--c-ah)">Browse Listings →</button>
</div>
</section>
<!-- FOOTER -->
<footer style="border-top:1px solid var(--c-bd);padding:22px 60px;">
<div style="max-width:1200px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;">
<div style="display:flex;align-items:center;gap:8px;">
<svg width="20" height="20" viewBox="0 0 26 26" fill="none"><rect width="26" height="26" rx="7" fill="var(--c-a)"/><path d="M6 9h14M6 13h9M6 17h11" stroke="white" stroke-width="2" stroke-linecap="round"/></svg>
<span style="font-size:14px;font-weight:700;color:var(--c-t);">Volana</span>
<span style="font-size:12px;color:var(--c-t3);margin-left:6px;">Trade freely. Pay finally.</span>
</div>
<div style="font-size:12px;color:var(--c-t3);">Built on Solana · Open-source smart contracts · No platform fees</div>
</div>
</footer>
</div>
</sc-if>
<!-- ── BROWSE ── -->
<sc-if value="{{ showBrowse }}" hint-placeholder-val="{{ false }}">
<div style="animation:fadeUp .22s ease;">
<!-- Hero -->
<div style="background:linear-gradient(135deg,var(--c-bg2) 0%,var(--c-bg) 100%);border-bottom:1px solid var(--c-bd);padding:28px 20px 24px;">
<div style="max-width:1320px;margin:0 auto;">
<h1 style="margin:0 0 5px;font-size:28px;font-weight:700;letter-spacing:-0.7px;color:var(--c-t);line-height:1.2;">Trade freely. Pay finally.</h1>
<p style="margin:0 0 16px;font-size:13px;color:var(--c-t2);line-height:1.5;">The marketplace nobody controls — built on Solana.</p>
<div style="display:flex;gap:7px;flex-wrap:nowrap;">
<span style="display:inline-flex;align-items:center;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:20px;padding:5px 12px;font-size:12px;font-weight:500;color:var(--c-g);white-space:nowrap;line-height:1;">✓ Final payments</span>
<span style="display:inline-flex;align-items:center;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:20px;padding:5px 12px;font-size:12px;font-weight:500;color:var(--c-t2);white-space:nowrap;line-height:1;">⬡ On-chain verified</span>
<span style="display:inline-flex;align-items:center;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:20px;padding:5px 12px;font-size:12px;font-weight:500;color:var(--c-t2);white-space:nowrap;line-height:1;">&lt;$0.001 fees</span>
<span style="display:inline-flex;align-items:center;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:20px;padding:5px 12px;font-size:12px;font-weight:500;color:var(--c-t2);white-space:nowrap;line-height:1;">🛡 Dispute protection</span>
</div>
</div>
</div>
<!-- Filter bar -->
<div style="background:var(--c-bg);border-bottom:1px solid var(--c-bd);padding:10px 20px;position:sticky;top:60px;z-index:90;">
<div style="max-width:1320px;margin:0 auto;display:flex;align-items:center;gap:6px;flex-wrap:wrap;">
<span style="font-size:12px;color:var(--c-t3);font-weight:500;margin-right:2px;">Currency</span>
<button onClick="{{ setFAll }}" style="background:{{ faBg }};color:{{ faC }};border:1px solid {{ faB }};border-radius:6px;padding:4px 11px;font-size:12px;cursor:pointer;font-weight:500;transition:all .12s;">All</button>
<button onClick="{{ setFSOL }}" style="background:{{ fsBg }};color:{{ fsC }};border:1px solid {{ fsB }};border-radius:6px;padding:4px 11px;font-size:12px;cursor:pointer;font-weight:500;transition:all .12s;">SOL</button>
<button onClick="{{ setFUSDC }}" style="background:{{ fuBg }};color:{{ fuC }};border:1px solid {{ fuB }};border-radius:6px;padding:4px 11px;font-size:12px;cursor:pointer;font-weight:500;transition:all .12s;">USDC</button>
<div style="width:1px;height:18px;background:var(--c-bd);margin:0 3px;"></div>
<span style="font-size:12px;color:var(--c-t3);font-weight:500;margin-right:2px;">Sort</span>
<button onClick="{{ setSN }}" style="background:{{ snBg }};color:{{ snC }};border:1px solid {{ snB }};border-radius:6px;padding:4px 11px;font-size:12px;cursor:pointer;font-weight:500;transition:all .12s;">Newest</button>
<button onClick="{{ setSL }}" style="background:{{ slBg }};color:{{ slC }};border:1px solid {{ slB }};border-radius:6px;padding:4px 11px;font-size:12px;cursor:pointer;font-weight:500;transition:all .12s;">Price ↑</button>
<button onClick="{{ setSH }}" style="background:{{ shBg }};color:{{ shC }};border:1px solid {{ shB }};border-radius:6px;padding:4px 11px;font-size:12px;cursor:pointer;font-weight:500;transition:all .12s;">Price ↓</button>
<div style="width:1px;height:18px;background:var(--c-bd);margin:0 3px;"></div>
<label style="display:flex;align-items:center;gap:6px;cursor:pointer;font-size:12px;color:var(--c-t2);">
<input type="checkbox" checked="{{ stockFilter }}" onChange="{{ toggleStock }}" style="width:14px;height:14px;accent-color:var(--c-a);cursor:pointer;"/>
In stock only
</label>
<div style="margin-left:auto;display:flex;gap:3px;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:7px;padding:3px;">
<button onClick="{{ setViewList }}" title="List view" style="background:{{ vlBg.bg }};color:{{ vlBg.c }};border:none;border-radius:4px;width:28px;height:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .12s;">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3h10M2 7h10M2 11h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
</button>
<button onClick="{{ setViewGrid }}" title="Grid view" style="background:{{ vgBg.bg }};color:{{ vgBg.c }};border:none;border-radius:4px;width:28px;height:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .12s;">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="1" y="1" width="5" height="5" rx="1" stroke="currentColor" stroke-width="1.5"/><rect x="8" y="1" width="5" height="5" rx="1" stroke="currentColor" stroke-width="1.5"/><rect x="1" y="8" width="5" height="5" rx="1" stroke="currentColor" stroke-width="1.5"/><rect x="8" y="8" width="5" height="5" rx="1" stroke="currentColor" stroke-width="1.5"/></svg>
</button>
</div>
</div>
</div>
<!-- ── LIST VIEW ── -->
<sc-if value="{{ isListView }}" hint-placeholder-val="{{ true }}">
<div style="max-width:960px;margin:0 auto;padding:20px 40px;display:flex;flex-direction:column;gap:10px;">
<sc-for list="{{ products }}" as="p" hint-placeholder-count="8">
<div onClick="{{ p.clickCard }}" style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:10px;cursor:pointer;display:flex;align-items:stretch;overflow:hidden;transition:border-color .12s,box-shadow .12s;" style-hover="border-color:var(--c-bd2);box-shadow:0 4px 20px rgba(0,0,0,.18);">
<!-- Image -->
<div style="width:180px;height:180px;flex-shrink:0;background:{{ p.bg }};display:flex;align-items:center;justify-content:center;font-size:66px;position:relative;overflow:hidden;">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 30% 25%,rgba(255,255,255,.07) 0%,transparent 60%);"></div>
<span style="position:relative;">{{ p.em }}</span>
</div>
<!-- Price — directly next to image -->
<div style="width:148px;flex-shrink:0;padding:18px 16px;display:flex;flex-direction:column;justify-content:center;border-left:1px solid var(--c-bd);">
<div style="line-height:1;margin-bottom:4px;">
<span style="font-size:26px;font-weight:800;color:var(--c-a);letter-spacing:-1px;">{{ p.priceVal }}</span><span style="font-size:13px;font-weight:500;color:var(--c-t3);margin-left:4px;letter-spacing:0.2px;">{{ p.cur }}</span>
</div>
<div style="font-size:11px;color:var(--c-t3);">≈ {{ p.usd }}</div>
<sc-if value="{{ p.showAvailBadge }}" hint-placeholder-val="{{ false }}">
<div style="margin-top:10px;color:{{ p.availC }};font-size:11px;font-weight:600;">{{ p.availLabel }}</div>
</sc-if>
</div>
<!-- Name + description -->
<div style="flex:1;padding:18px 20px;min-width:0;border-left:1px solid var(--c-bd);">
<div style="font-size:15px;font-weight:600;color:var(--c-t);line-height:1.35;margin-bottom:6px;letter-spacing:-0.1px;">{{ p.name }}</div>
<div style="font-size:12px;color:var(--c-t3);line-height:1.55;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:10px;">{{ p.desc }}</div>
<div style="display:flex;align-items:center;gap:10px;font-size:11px;color:var(--c-t3);">
<span>{{ p.cat }}</span>
<span>·</span>
<span style="font-family:'DM Mono',monospace;">{{ p.seller }}</span>
<sc-if value="{{ p.hasAlt }}" hint-placeholder-val="{{ false }}">
<span>· also {{ p.altLabel }}</span>
</sc-if>
</div>
</div>
<!-- Buy -->
<div style="width:136px;flex-shrink:0;padding:18px 16px;display:flex;flex-direction:column;justify-content:center;gap:7px;border-left:1px solid var(--c-bd);">
<button onClick="{{ p.clickBuy }}" disabled="{{ p.isOut }}" style="background:{{ p.buyBg }};color:{{ p.buyC }};border:none;border-radius:7px;padding:10px;font-size:13px;font-weight:600;cursor:{{ p.buyCursor }};width:100%;transition:opacity .12s;" style-hover="opacity:.85">{{ p.buyLabel }}</button>
<button onClick="{{ p.clickCard }}" style="background:none;border:1px solid var(--c-bd);color:var(--c-t2);border-radius:7px;padding:7px;font-size:12px;cursor:pointer;width:100%;" style-hover="border-color:var(--c-bd2);color:var(--c-t)">View listing</button>
</div>
</div>
</sc-for>
</div>
</sc-if>
<!-- ── GRID VIEW ── -->
<sc-if value="{{ isGridView }}" hint-placeholder-val="{{ false }}">
<div style="max-width:1320px;margin:0 auto;padding:20px;display:grid;grid-template-columns:repeat(auto-fill,minmax(205px,1fr));gap:11px;">
<sc-for list="{{ products }}" as="p" hint-placeholder-count="12">
<div onClick="{{ p.clickCard }}" style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:10px;overflow:hidden;cursor:pointer;display:flex;flex-direction:column;transition:transform .14s,box-shadow .14s,border-color .14s;" style-hover="transform:translateY(-2px);box-shadow:0 8px 28px rgba(0,0,0,.22);border-color:var(--c-bd2);">
<div style="height:145px;background:{{ p.bg }};display:flex;align-items:center;justify-content:center;font-size:50px;position:relative;flex-shrink:0;">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 30% 25%,rgba(255,255,255,.07) 0%,transparent 65%);"></div>
<span style="position:relative;">{{ p.em }}</span>
</div>
<div style="padding:10px 10px 0;flex:1;display:flex;flex-direction:column;gap:3px;">
<div style="font-size:13px;font-weight:600;color:var(--c-t);line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;">{{ p.name }}</div>
<div style="font-size:11px;color:var(--c-t3);font-family:'DM Mono',monospace;">{{ p.seller }}</div>
<div style="margin-top:5px;display:flex;align-items:center;justify-content:space-between;gap:4px;flex-wrap:wrap;">
<span style="font-size:15px;font-weight:700;color:var(--c-a);letter-spacing:-0.3px;">{{ p.price }}</span>
<span style="color:{{ p.availC }};background:{{ p.availBg }};border:1px solid {{ p.availBorder }};padding:2px 7px;border-radius:4px;font-size:10px;font-weight:600;white-space:nowrap;">{{ p.availLabel }}</span>
</div>
</div>
<button onClick="{{ p.clickBuy }}" disabled="{{ p.isOut }}" style="margin:8px 10px 10px;border:none;border-radius:6px;padding:8px;font-size:13px;font-weight:600;cursor:{{ p.buyCursor }};background:{{ p.buyBg }};color:{{ p.buyC }};transition:opacity .12s;" style-hover="opacity:.85">{{ p.buyLabel }}</button>
</div>
</sc-for>
</div>
</sc-if>
</div>
</sc-if>
<!-- ── LISTING DETAIL ── -->
<sc-if value="{{ showListing }}" hint-placeholder-val="{{ false }}">
<div style="max-width:1320px;margin:0 auto;padding:24px 20px;animation:fadeUp .22s ease;">
<button onClick="{{ goBack }}" style="display:flex;align-items:center;gap:6px;background:none;border:none;color:var(--c-t2);cursor:pointer;padding:6px 0;font-size:13px;margin-bottom:20px;" style-hover="color:var(--c-t)">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 4l-4 4 4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
Back to Browse
</button>
<div style="display:grid;grid-template-columns:1fr 340px;gap:32px;align-items:start;">
<!-- Left col -->
<div>
<div style="height:360px;background:{{ listing.bg }};border-radius:14px;display:flex;align-items:center;justify-content:center;font-size:120px;position:relative;overflow:hidden;margin-bottom:24px;">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 35% 30%,rgba(255,255,255,.08) 0%,transparent 55%);"></div>
<div style="position:absolute;bottom:0;left:0;right:0;height:80px;background:linear-gradient(to top,rgba(0,0,0,.3),transparent);"></div>
<span style="position:relative;">{{ listing.em }}</span>
</div>
<h1 style="margin:0 0 10px;font-size:24px;font-weight:700;letter-spacing:-0.5px;line-height:1.25;color:var(--c-t);">{{ listing.name }}</h1>
<p style="margin:0 0 20px;font-size:14px;color:var(--c-t2);line-height:1.6;">{{ listing.desc }}</p>
<div style="display:flex;align-items:center;gap:10px;padding:12px 16px;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:10px;margin-bottom:12px;">
<svg width="18" height="18" viewBox="0 0 18 18" fill="none"><circle cx="9" cy="9" r="8" stroke="var(--c-a)" stroke-width="1.5"/><path d="M6 9l2 2 4-4" stroke="var(--c-a)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
<div>
<div style="font-size:12px;font-weight:600;color:var(--c-t);">Verified on Solana</div>
<div style="font-size:11px;color:var(--c-t3);font-family:'DM Mono',monospace;margin-top:1px;">{{ listing.seller }}</div>
</div>
<button onClick="{{ copySeller }}" style="margin-left:auto;background:none;border:none;cursor:pointer;color:var(--c-t3);font-size:11px;padding:4px 8px;border-radius:5px;" style-hover="color:var(--c-t);background:var(--c-surf2)">Copy</button>
</div>
<div style="padding:12px 16px;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:10px;">
<div style="font-size:11px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px;">About this listing</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
<div><div style="font-size:11px;color:var(--c-t3);">Category</div><div style="font-size:13px;color:var(--c-t);font-weight:500;margin-top:2px;">{{ listing.cat }}</div></div>
<div><div style="font-size:11px;color:var(--c-t3);">Available</div><div style="font-size:13px;color:var(--c-t);font-weight:500;margin-top:2px;">{{ listing.qty }} units</div></div>
<div><div style="font-size:11px;color:var(--c-t3);">Currency</div><div style="font-size:13px;color:var(--c-t);font-weight:500;margin-top:2px;">{{ listing.cur }}</div></div>
<div><div style="font-size:11px;color:var(--c-t3);">Listing ID</div><div style="font-size:12px;color:var(--c-t3);font-family:'DM Mono',monospace;margin-top:2px;">#{{ listing.id }}{{ listing.id }}{{ listing.id }}{{ listing.id }}</div></div>
</div>
</div>
<!-- Customers also bought -->
<div style="margin-top:28px;">
<div style="font-size:16px;font-weight:700;letter-spacing:-0.3px;color:var(--c-t);margin-bottom:14px;">Customers also bought</div>
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px;">
<sc-for list="{{ relatedProducts }}" as="rp" hint-placeholder-count="6">
<div onClick="{{ rp.clickCard }}" style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:9px;overflow:hidden;cursor:pointer;transition:border-color .12s,transform .12s;" style-hover="border-color:var(--c-bd2);transform:translateY(-2px);">
<div style="height:100px;background:{{ rp.bg }};display:flex;align-items:center;justify-content:center;font-size:38px;position:relative;">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 30% 25%,rgba(255,255,255,.07) 0%,transparent 60%);"></div>
<span style="position:relative;">{{ rp.em }}</span>
</div>
<div style="padding:9px 10px;">
<div style="font-size:12px;font-weight:600;color:var(--c-t);line-height:1.3;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:5px;">{{ rp.name }}</div>
<div style="font-size:13px;font-weight:700;color:var(--c-a);">{{ rp.price }}</div>
</div>
</div>
</sc-for>
</div>
</div>
</div>
<!-- Right col sticky -->
<div style="position:sticky;top:76px;background:var(--c-surf);border:1px solid var(--c-bd);border-radius:14px;padding:22px;display:flex;flex-direction:column;gap:16px;">
<!-- Price -->
<div>
<div style="font-size:32px;font-weight:700;color:var(--c-t);letter-spacing:-0.8px;line-height:1;">{{ listing.price }}</div>
<div style="font-size:14px;color:var(--c-t3);margin-top:3px;">≈ {{ listing.usd }} USD</div>
<div style="margin-top:10px;">
<span style="color:{{ lAvailC }};background:{{ lAvailBg }};border:1px solid {{ lAvailBorder }};padding:3px 10px;border-radius:5px;font-size:12px;font-weight:600;">{{ lAvailLabel }}</span>
</div>
</div>
<div style="height:1px;background:var(--c-bd);"></div>
<!-- Currency selector -->
<sc-if value="{{ lHasAlt }}" hint-placeholder-val="{{ false }}">
<div>
<div style="font-size:11px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px;">Pay with</div>
<div style="display:flex;gap:6px;">
<button onClick="{{ lSetCurPrimary }}" style="background:{{ lcpBg }};color:{{ lcpC }};border:1px solid {{ lcpB }};border-radius:7px;padding:6px 14px;font-size:13px;cursor:pointer;font-weight:500;transition:all .12s;">{{ lCurPrimary }}</button>
<button onClick="{{ lSetCurAlt }}" style="background:{{ lcaBg }};color:{{ lcaC }};border:1px solid {{ lcaB }};border-radius:7px;padding:6px 14px;font-size:13px;cursor:pointer;font-weight:500;transition:all .12s;">{{ lCurAlt }}</button>
</div>
</div>
<div style="height:1px;background:var(--c-bd);"></div>
</sc-if>
<!-- Resolver -->
<div>
<div style="font-size:11px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px;">Dispute Protection</div>
<sc-for list="{{ resolvers }}" as="r" hint-placeholder-count="3">
<button onClick="{{ r.selectIt }}" style="background:{{ r.rBg }};border:1px solid {{ r.rBorder }};border-radius:8px;padding:9px 11px;cursor:pointer;width:100%;text-align:left;margin-bottom:5px;display:block;transition:all .12s;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:2px;">
<span style="font-size:13px;font-weight:600;color:{{ r.rNameC }};">{{ r.name }}</span>
<span style="font-size:12px;font-weight:600;font-family:'DM Mono',monospace;color:{{ r.rNameC }};">{{ r.fee }}</span>
</div>
<div style="font-size:11px;color:var(--c-t3);">{{ r.type }} · {{ r.wins }}% buyer-favorable</div>
</button>
</sc-for>
<div style="font-size:11px;color:var(--c-t3);margin-top:3px;">Fee only charged if dispute is adjudicated.</div>
</div>
<div style="height:1px;background:var(--c-bd);"></div>
<!-- Buy button -->
<button onClick="{{ onBuyNow }}" disabled="{{ lIsOut }}" style="background:{{ lBuyBg }};color:{{ lBuyC }};border:none;border-radius:10px;padding:15px;font-size:15px;font-weight:700;width:100%;cursor:{{ lBuyCursor }};letter-spacing:-0.2px;transition:opacity .12s;" style-hover="opacity:.88">{{ lBuyLabel }}</button>
<!-- Trust badges -->
<div style="display:flex;gap:6px;flex-wrap:wrap;">
<span style="display:flex;align-items:center;gap:5px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:20px;padding:4px 9px;font-size:11px;font-weight:500;color:var(--c-g);">✓ Final Payment</span>
<span style="display:flex;align-items:center;gap:5px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:20px;padding:4px 9px;font-size:11px;font-weight:500;color:var(--c-t2);">🛡 Dispute Cover</span>
<span style="display:flex;align-items:center;gap:5px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:20px;padding:4px 9px;font-size:11px;font-weight:500;color:var(--c-t2);">⬡ On-chain</span>
</div>
<div style="font-size:11px;color:var(--c-t3);text-align:center;line-height:1.5;">Funds held in secure escrow until you confirm receipt.</div>
</div>
</div>
</div>
</sc-if>
<!-- ── MY ORDERS ── -->
<sc-if value="{{ showOrders }}" hint-placeholder-val="{{ false }}">
<div style="max-width:900px;margin:0 auto;padding:28px 20px;animation:fadeUp .22s ease;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;">
<h2 style="margin:0;font-size:22px;font-weight:700;letter-spacing:-0.5px;">My Orders</h2>
<button onClick="{{ goHome }}" style="background:none;border:none;color:var(--c-t2);cursor:pointer;font-size:13px;padding:6px 0;" style-hover="color:var(--c-t)">Continue browsing →</button>
</div>
<div style="display:flex;flex-direction:column;gap:8px;">
<sc-for list="{{ orders }}" as="o" hint-placeholder-count="3">
<div onClick="{{ o.clickOrder }}" style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:10px;padding:14px 16px;cursor:pointer;display:flex;align-items:center;gap:14px;transition:border-color .12s;" style-hover="border-color:var(--c-bd2);">
<div style="font-size:28px;line-height:1;">{{ o.em }}</div>
<div style="flex:1;min-width:0;">
<div style="font-size:14px;font-weight:600;color:var(--c-t);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">{{ o.name }}</div>
<div style="font-size:12px;color:var(--c-t3);font-family:'DM Mono',monospace;margin-top:2px;">{{ o.seller }}</div>
</div>
<div style="text-align:right;flex-shrink:0;">
<div style="font-size:15px;font-weight:700;color:var(--c-t);letter-spacing:-0.3px;">{{ o.amt }}</div>
<div style="font-size:11px;color:var(--c-t3);margin-top:2px;">{{ o.date }}</div>
</div>
<div style="flex-shrink:0;">
<span style="color:{{ o.sColor }};background:{{ o.sBg }};border:1px solid {{ o.sBorder }};padding:3px 9px;border-radius:5px;font-size:11px;font-weight:600;white-space:nowrap;">{{ o.statusLabel }}</span>
</div>
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;color:var(--c-t3);"><path d="M5 2l5 5-5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
</sc-for>
</div>
</div>
</sc-if>
<!-- ── ORDER DETAIL ── -->
<sc-if value="{{ showOrderDetail }}" hint-placeholder-val="{{ false }}">
<div style="max-width:720px;margin:0 auto;padding:28px 20px;animation:fadeUp .22s ease;">
<button onClick="{{ goBackOrders }}" style="display:flex;align-items:center;gap:6px;background:none;border:none;color:var(--c-t2);cursor:pointer;padding:6px 0;font-size:13px;margin-bottom:20px;" style-hover="color:var(--c-t)">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 4l-4 4 4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
My Orders
</button>
<div style="background:var(--c-surf);border:1px solid var(--c-bd);border-radius:14px;overflow:hidden;">
<!-- Header -->
<div style="padding:20px 22px;border-bottom:1px solid var(--c-bd);display:flex;align-items:flex-start;justify-content:space-between;gap:12px;">
<div>
<div style="font-size:12px;color:var(--c-t3);margin-bottom:4px;">Order placed {{ od.date }}</div>
<div style="font-size:18px;font-weight:700;color:var(--c-t);letter-spacing:-0.3px;">{{ od.name }}</div>
<div style="font-size:13px;color:var(--c-t3);font-family:'DM Mono',monospace;margin-top:4px;">{{ od.seller }}</div>
</div>
<div style="text-align:right;flex-shrink:0;">
<div style="font-size:20px;font-weight:700;color:var(--c-t);">{{ od.amt }}</div>
<span style="color:{{ od.sColor }};background:{{ od.sBg }};border:1px solid {{ od.sBorder }};padding:3px 9px;border-radius:5px;font-size:11px;font-weight:600;display:inline-block;margin-top:6px;">{{ od.statusLabel }}</span>
</div>
</div>
<!-- Progress stepper -->
<div style="padding:24px 22px;border-bottom:1px solid var(--c-bd);">
<div style="font-size:12px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:18px;">Order Progress</div>
<div style="display:flex;align-items:flex-start;gap:0;">
<!-- Step 1 -->
<div style="display:flex;flex-direction:column;align-items:center;flex:1;">
<div style="width:28px;height:28px;border-radius:50%;background:var(--c-g);display:flex;align-items:center;justify-content:center;font-size:12px;color:#000;font-weight:700;margin-bottom:8px;flex-shrink:0;"></div>
<div style="font-size:11px;font-weight:600;color:var(--c-g);text-align:center;line-height:1.3;">Payment<br/>Held</div>
</div>
<div style="flex:1;height:2px;background:{{ od.step12Bg }};margin-top:13px;transition:background .3s;"></div>
<!-- Step 2 -->
<div style="display:flex;flex-direction:column;align-items:center;flex:1;">
<div style="width:28px;height:28px;border-radius:50%;background:{{ od.dot2Bg }};display:flex;align-items:center;justify-content:center;font-size:12px;color:{{ od.dot2C }};font-weight:700;margin-bottom:8px;flex-shrink:0;transition:all .3s;">{{ od.dot2Text }}</div>
<div style="font-size:11px;font-weight:600;color:{{ od.s2Color }};text-align:center;line-height:1.3;transition:color .3s;">Seller<br/>Confirms</div>
</div>
<div style="flex:1;height:2px;background:{{ od.step23Bg }};margin-top:13px;transition:background .3s;"></div>
<!-- Step 3 -->
<div style="display:flex;flex-direction:column;align-items:center;flex:1;">
<div style="width:28px;height:28px;border-radius:50%;background:{{ od.dot3Bg }};display:flex;align-items:center;justify-content:center;font-size:12px;color:{{ od.dot3C }};font-weight:700;margin-bottom:8px;flex-shrink:0;transition:all .3s;">{{ od.dot3Text }}</div>
<div style="font-size:11px;font-weight:600;color:{{ od.s3Color }};text-align:center;line-height:1.3;transition:color .3s;">You Confirm<br/>Receipt</div>
</div>
</div>
</div>
<!-- Escrow info -->
<div style="padding:16px 22px;border-bottom:1px solid var(--c-bd);background:var(--c-surf2);">
<div style="font-size:13px;color:var(--c-t2);line-height:1.5;">
<span style="font-weight:600;color:var(--c-t);">{{ od.amt }}</span> is locked in a secure on-chain escrow. Funds are released to the seller only after you confirm receipt — no third party can touch them.
</div>
</div>
<!-- Actions -->
<div style="padding:18px 22px;display:flex;gap:10px;flex-wrap:wrap;">
<sc-if value="{{ od.canCancel }}" hint-placeholder-val="{{ false }}">
<button onClick="{{ od.cancelOrder }}" style="border:1px solid var(--c-r);background:var(--c-rd);color:var(--c-r);border-radius:8px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;" style-hover="opacity:.85">Cancel Order (Full Refund)</button>
</sc-if>
<sc-if value="{{ od.canConfirm }}" hint-placeholder-val="{{ false }}">
<button onClick="{{ od.confirmReceipt }}" style="background:var(--c-g);color:#000;border:none;border-radius:8px;padding:10px 18px;font-size:14px;font-weight:700;cursor:pointer;" style-hover="opacity:.88">Confirm Receipt — Release Payment</button>
</sc-if>
<button onClick="{{ od.goToListing }}" style="background:none;border:1px solid var(--c-bd);color:var(--c-t2);border-radius:8px;padding:10px 18px;font-size:14px;cursor:pointer;" style-hover="border-color:var(--c-bd2);color:var(--c-t)">View Listing →</button>
</div>
</div>
</div>
</sc-if>
</div><!-- /pages -->
<!-- ══════ WALLET MODAL ══════ -->
<sc-if value="{{ showWalletModal }}" hint-placeholder-val="{{ false }}">
<div style="position:fixed;inset:0;background:rgba(4,4,10,.78);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);z-index:500;display:flex;align-items:center;justify-content:center;padding:20px;" onClick="{{ closeModal }}">
<div onClick="{{ stopProp }}" style="background:var(--c-surf);border:1px solid var(--c-bd2);border-radius:16px;padding:28px;width:360px;max-width:100%;box-shadow:0 24px 64px rgba(0,0,0,.5);animation:fadeUp .2s ease;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;">
<div>
<div style="font-size:18px;font-weight:700;color:var(--c-t);letter-spacing:-0.3px;">Connect Wallet</div>
<div style="font-size:13px;color:var(--c-t2);margin-top:3px;">Choose your Solana wallet</div>
</div>
<button onClick="{{ closeModal }}" style="background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:6px;width:30px;height:30px;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;color:var(--c-t2);" style-hover="color:var(--c-t)">×</button>
</div>
<div style="display:flex;flex-direction:column;gap:8px;margin-bottom:20px;">
<button onClick="{{ connectPhantom }}" style="display:flex;align-items:center;gap:12px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:13px 16px;cursor:pointer;transition:border-color .12s;" style-hover="border-color:var(--c-a)">
<span style="font-size:24px;">👻</span>
<div style="text-align:left;">
<div style="font-size:14px;font-weight:600;color:var(--c-t);">Phantom</div>
<div style="font-size:11px;color:var(--c-t3);">Most popular Solana wallet</div>
</div>
<svg style="margin-left:auto;" width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M4 2l5 5-5 5" stroke="var(--c-t3)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<button onClick="{{ connectSolflare }}" style="display:flex;align-items:center;gap:12px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:13px 16px;cursor:pointer;transition:border-color .12s;" style-hover="border-color:var(--c-a)">
<span style="font-size:24px;">🌊</span>
<div style="text-align:left;">
<div style="font-size:14px;font-weight:600;color:var(--c-t);">Solflare</div>
<div style="font-size:11px;color:var(--c-t3);">Built for power users</div>
</div>
<svg style="margin-left:auto;" width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M4 2l5 5-5 5" stroke="var(--c-t3)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<button onClick="{{ connectBackpack }}" style="display:flex;align-items:center;gap:12px;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:13px 16px;cursor:pointer;transition:border-color .12s;" style-hover="border-color:var(--c-a)">
<span style="font-size:24px;">🎒</span>
<div style="text-align:left;">
<div style="font-size:14px;font-weight:600;color:var(--c-t);">Backpack</div>
<div style="font-size:11px;color:var(--c-t3);">xNFT & multi-chain wallet</div>
</div>
<svg style="margin-left:auto;" width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M4 2l5 5-5 5" stroke="var(--c-t3)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
</div>
<div style="text-align:center;font-size:12px;color:var(--c-t3);line-height:1.5;">No wallet? <span style="color:var(--c-a);font-weight:500;">Download Phantom</span> — free &amp; open source.</div>
</div>
</div>
</sc-if>
<!-- ══════ CHECKOUT MODAL ══════ -->
<sc-if value="{{ showCheckout }}" hint-placeholder-val="{{ false }}">
<div style="position:fixed;inset:0;background:rgba(4,4,10,.78);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);z-index:500;display:flex;align-items:center;justify-content:center;padding:20px;">
<div style="background:var(--c-surf);border:1px solid var(--c-bd2);border-radius:16px;width:440px;max-width:100%;max-height:90vh;overflow-y:auto;box-shadow:0 24px 64px rgba(0,0,0,.5);animation:fadeUp .2s ease;">
<!-- REVIEW STEP -->
<sc-if value="{{ cReview }}" hint-placeholder-val="{{ true }}">
<div style="padding:26px;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;">
<div style="font-size:18px;font-weight:700;color:var(--c-t);letter-spacing:-0.3px;">Place Order</div>
<button onClick="{{ closeModal }}" style="background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:6px;width:30px;height:30px;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;color:var(--c-t2);" style-hover="color:var(--c-t)">×</button>
</div>
<!-- Product summary -->
<div style="display:flex;gap:12px;align-items:center;background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:12px;margin-bottom:18px;">
<div style="width:44px;height:44px;border-radius:8px;background:{{ cListing.bg }};display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">{{ cListing.em }}</div>
<div style="min-width:0;">
<div style="font-size:13px;font-weight:600;color:var(--c-t);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">{{ cListing.name }}</div>
<div style="font-size:11px;color:var(--c-t3);font-family:'DM Mono',monospace;margin-top:2px;">{{ cListing.seller }}</div>
</div>
</div>
<!-- Payment -->
<div style="background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:14px;margin-bottom:12px;">
<div style="font-size:11px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:10px;">Payment</div>
<div style="display:flex;align-items:baseline;gap:8px;">
<span style="font-size:22px;font-weight:700;color:var(--c-t);letter-spacing:-0.5px;">{{ cAmount }}</span>
<span style="font-size:13px;color:var(--c-t3);">≈ {{ cUsd }} USD</span>
</div>
<div style="font-size:11px;color:var(--c-t3);margin-top:8px;line-height:1.4;">Slippage tolerance: 0.5% · Funds locked in escrow on confirm.</div>
</div>
<!-- Resolver -->
<div style="background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:14px;margin-bottom:20px;">
<div style="font-size:11px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:10px;">Dispute Protection</div>
<div style="display:flex;align-items:center;justify-content:space-between;">
<div>
<div style="font-size:13px;font-weight:600;color:var(--c-t);">{{ cResolver.name }}</div>
<div style="font-size:11px;color:var(--c-t3);margin-top:2px;">{{ cResolver.fee }} fee · {{ cResolver.type }} · {{ cResolver.wins }}% buyer-favorable</div>
</div>
<span style="font-size:11px;color:var(--c-a);font-weight:500;">✓ Selected</span>
</div>
<div style="font-size:11px;color:var(--c-t3);margin-top:8px;">Fee only charged if a dispute is actually adjudicated.</div>
</div>
<div style="display:flex;gap:8px;">
<button onClick="{{ closeModal }}" style="flex:1;background:none;border:1px solid var(--c-bd);color:var(--c-t2);border-radius:8px;padding:12px;font-size:14px;cursor:pointer;" style-hover="border-color:var(--c-bd2);color:var(--c-t)">Cancel</button>
<button onClick="{{ confirmOrder }}" style="flex:2;background:var(--c-a);color:#fff;border:none;border-radius:8px;padding:12px;font-size:14px;font-weight:700;cursor:pointer;letter-spacing:-0.2px;" style-hover="background:var(--c-ah)">Confirm &amp; Place Order →</button>
</div>
</div>
</sc-if>
<!-- PENDING STEP -->
<sc-if value="{{ cPending }}" hint-placeholder-val="{{ false }}">
<div style="padding:48px 26px;text-align:center;">
<div style="width:56px;height:56px;border-radius:50%;border:3px solid var(--c-bd2);border-top-color:var(--c-a);animation:spin 0.7s linear infinite;margin:0 auto 20px;"></div>
<div style="font-size:18px;font-weight:700;color:var(--c-t);margin-bottom:6px;">Confirming on Solana…</div>
<div style="font-size:13px;color:var(--c-t2);line-height:1.5;">Approve the transaction in your wallet.<br/>This takes a few seconds.</div>
</div>
</sc-if>
<!-- SUCCESS STEP -->
<sc-if value="{{ cSuccess }}" hint-placeholder-val="{{ false }}">
<div style="padding:26px;animation:fadeUp .25s ease;">
<div style="text-align:center;margin-bottom:20px;">
<div style="width:52px;height:52px;border-radius:50%;background:var(--c-gd);border:1px solid var(--c-g);display:flex;align-items:center;justify-content:center;font-size:22px;margin:0 auto 14px;"></div>
<div style="font-size:20px;font-weight:700;color:var(--c-t);letter-spacing:-0.4px;">Order Placed!</div>
<div style="font-size:13px;color:var(--c-t2);margin-top:6px;line-height:1.5;"><span style="font-weight:600;color:var(--c-t);">{{ cAmount }}</span> is now held in secure escrow.<br/>The seller has been notified.</div>
</div>
<div style="background:var(--c-surf2);border:1px solid var(--c-bd);border-radius:10px;padding:14px;margin-bottom:20px;">
<div style="font-size:11px;font-weight:600;color:var(--c-t3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:10px;">What happens next</div>
<div style="display:flex;flex-direction:column;gap:8px;">
<div style="display:flex;gap:10px;align-items:flex-start;">
<span style="width:18px;height:18px;border-radius:50%;background:var(--c-ad);border:1px solid var(--c-a);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:var(--c-a);flex-shrink:0;margin-top:1px;">1</span>
<span style="font-size:13px;color:var(--c-t2);">Seller confirms within 2448h</span>
</div>
<div style="display:flex;gap:10px;align-items:flex-start;">
<span style="width:18px;height:18px;border-radius:50%;background:var(--c-ad);border:1px solid var(--c-a);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:var(--c-a);flex-shrink:0;margin-top:1px;">2</span>
<span style="font-size:13px;color:var(--c-t2);">You receive the goods</span>
</div>
<div style="display:flex;gap:10px;align-items:flex-start;">
<span style="width:18px;height:18px;border-radius:50%;background:var(--c-ad);border:1px solid var(--c-a);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:var(--c-a);flex-shrink:0;margin-top:1px;">3</span>
<span style="font-size:13px;color:var(--c-t2);">Confirm receipt → seller gets paid</span>
</div>
</div>
</div>
<div style="display:flex;gap:8px;">
<button onClick="{{ continueShopping }}" style="flex:1;background:none;border:1px solid var(--c-bd);color:var(--c-t2);border-radius:8px;padding:12px;font-size:14px;cursor:pointer;" style-hover="border-color:var(--c-bd2);color:var(--c-t)">Continue Shopping</button>
<button onClick="{{ viewOrders }}" style="flex:1;background:var(--c-a);color:#fff;border:none;border-radius:8px;padding:12px;font-size:14px;font-weight:600;cursor:pointer;" style-hover="background:var(--c-ah)">View My Orders</button>
</div>
</div>
</sc-if>
</div>
</div>
</sc-if>
<!-- ══════ TOAST ══════ -->
<sc-if value="{{ toastVisible }}" hint-placeholder-val="{{ false }}">
<div style="position:fixed;bottom:24px;right:24px;background:{{ toastBg }};border:1px solid {{ toastBorder }};color:{{ toastC }};border-radius:9px;padding:11px 16px;font-size:13px;font-weight:500;z-index:600;box-shadow:0 8px 24px rgba(0,0,0,.3);animation:slideIn .2s ease;max-width:280px;">{{ toastMsg }}</div>
</sc-if>
</div><!-- /root -->
</x-dc>
<script type="text/x-dc" data-dc-script data-props="{
&quot;$preview&quot;: {&quot;width&quot;: 1440, &quot;height&quot;: 900},
&quot;initialTheme&quot;: {&quot;editor&quot;: &quot;enum&quot;, &quot;options&quot;: [&quot;dark&quot;, &quot;light&quot;], &quot;default&quot;: &quot;dark&quot;, &quot;section&quot;: &quot;Appearance&quot;},
&quot;accentColor&quot;: {&quot;editor&quot;: &quot;color&quot;, &quot;default&quot;: &quot;#9945ff&quot;, &quot;section&quot;: &quot;Appearance&quot;}
}">
class Component extends DCLogic {
state = {
page: 'home',
listingId: 0,
modal: null,
step: 'review',
wallet: false,
addr: 'Gh9Z…k3mP',
theme: 'dark',
toast: null,
toastType: 'info',
search: '',
curFilter: 'all',
stockFilter: true,
sort: 'newest',
currency: 'SOL',
resolverId: 0,
orderId: 0,
pendingId: null,
walletOpen: false,
viewMode: 'list',
};
_L = [
{id:0,name:'MacBook Pro 14" M3 Pro',desc:'Factory sealed. 18GB Unified Memory, 512GB SSD, Space Black. International keyboard layout.',price:'2.4 SOL',priceNum:2.4,cur:'SOL',usd:'$288',qty:5,seller:'Gh9Z…mF8k',bg:'#0a1828',em:'💻',alt:['USDC'],cat:'Electronics'},
{id:1,name:'Adobe Photoshop Lifetime Key',desc:'One-time activation code. Non-subscription. Valid for 2 devices on Windows and macOS.',price:'45 USDC',priceNum:45,cur:'USDC',usd:'$45',qty:12,seller:'Bx3K…7pRq',bg:'#001230',em:'🎨',alt:['SOL'],cat:'Software'},
{id:2,name:'Air Jordan 1 Retro "Shadow" US 10',desc:'Deadstock. Black/Particle Grey/White. Original box, tissue paper and receipt. Zero wears.',price:'180 USDC',priceNum:180,cur:'USDC',usd:'$180',qty:1,seller:'Qm4R…nL2w',bg:'#180800',em:'👟',alt:[],cat:'Fashion'},
{id:3,name:'Custom 65% Mechanical Keyboard',desc:'Lubed Gateron Yellow Pro V2 switches. POM plate, anodized aluminum case. USB-C cable included.',price:'0.9 SOL',priceNum:0.9,cur:'SOL',usd:'$108',qty:3,seller:'Kx7P…2mJc',bg:'#0a1810',em:'⌨️',alt:['USDC'],cat:'Electronics'},
{id:4,name:'Midjourney Pro Plan (1 Year)',desc:'Full-year activation code. 30 fast GPU hours/month, unlimited relaxed, private and stealth mode.',price:'120 USDC',priceNum:120,cur:'USDC',usd:'$120',qty:8,seller:'Pp1L…sY9v',bg:'#120820',em:'🖼️',alt:[],cat:'Software'},
{id:5,name:'Sony WH-1000XM5 Headphones',desc:'Brand new, factory sealed. Midnight Black. 30-hour battery. Industry-leading noise cancellation.',price:'1.8 SOL',priceNum:1.8,cur:'SOL',usd:'$216',qty:0,seller:'Fx2T…oK5r',bg:'#0a0a14',em:'🎧',alt:[],cat:'Electronics'},
{id:6,name:'iPad Pro 12.9" M2 (256GB Wi-Fi)',desc:'Silver. Opened for 2 hours of testing only. AppleCare+ until June 2026. Original box included.',price:'3.2 SOL',priceNum:3.2,cur:'SOL',usd:'$384',qty:2,seller:'Rv8W…eC1x',bg:'#081420',em:'📱',alt:['USDC'],cat:'Electronics'},
{id:7,name:'Figma Professional (1 Year)',desc:'Team seat. Unlimited projects, 180-day version history, dev mode and advanced prototyping.',price:'60 USDC',priceNum:60,cur:'USDC',usd:'$60',qty:20,seller:'Mn6S…hB3z',bg:'#180a00',em:'✏️',alt:['SOL'],cat:'Software'},
{id:8,name:'Supreme Box Logo Hoodie — M',desc:'FW23 White. Unworn, original tags attached. Comes in original Supreme bag. Firm price.',price:'220 USDC',priceNum:220,cur:'USDC',usd:'$220',qty:1,seller:'Yx5A…dN7u',bg:'#180008',em:'🧥',alt:[],cat:'Fashion'},
{id:9,name:'Nintendo Switch OLED (White)',desc:'Excellent condition. Original Joy-Con, dock, power adapter, HDMI cable. Screen is pristine.',price:'1.2 SOL',priceNum:1.2,cur:'SOL',usd:'$144',qty:4,seller:'Jc0M…pQ4y',bg:'#0e0d18',em:'🕹️',alt:['USDC'],cat:'Electronics'},
{id:10,name:'myshop.sol Domain Name',desc:'Premium 3-year .sol domain registration. Currently parked. Instant transfer to your wallet on purchase.',price:'0.5 SOL',priceNum:0.5,cur:'SOL',usd:'$60',qty:1,seller:'Zg3F…wR6t',bg:'#0e0820',em:'🌐',alt:[],cat:'Crypto'},
{id:11,name:'Rolex Submariner 116610LN',desc:'Ref 116610LN, 2019. Full box and papers. Last serviced June 2024 by Rolex-authorized RSC.',price:'8.5 SOL',priceNum:8.5,cur:'SOL',usd:'$1,020',qty:1,seller:'Wh7N…iE2s',bg:'#081215',em:'⌚',alt:['USDC'],cat:'Luxury'},
];
_R = [
{id:0,name:'ShieldArb',desc:'Human arbitrators with 24h response.',fee:'0.5%',type:'Human',wins:94,total:1247},
{id:1,name:'FairDAO',desc:'Community-governed DAO for digital goods.',fee:'1.0%',type:'DAO',wins:89,total:823},
{id:2,name:'QuickResolve',desc:'AI-assisted, resolves in under 2 hours.',fee:'1.5%',type:'Automated',wins:96,total:3102},
];
_O = [
{id:0,lid:0,name:'MacBook Pro 14" M3 Pro',amt:'2.4 SOL',status:'AwaitingConfirm',date:'2 days ago',seller:'Gh9Z…mF8k',em:'💻'},
{id:1,lid:1,name:'Adobe Photoshop Lifetime Key',amt:'45 USDC',status:'Active',date:'5 days ago',seller:'Bx3K…7pRq',em:'🎨'},
{id:2,lid:7,name:'Figma Professional (1 Year)',amt:'60 USDC',status:'Complete',date:'12 days ago',seller:'Mn6S…hB3z',em:'✏️'},
];
_tt = null;
_toast(msg, type = 'info') {
clearTimeout(this._tt);
this.setState({ toast: msg, toastType: type });
this._tt = setTimeout(() => this.setState({ toast: null }), 3000);
}
_si(st) {
const m = {
AwaitingConfirm: { label:'Awaiting Confirm', c:'var(--c-y)', bg:'var(--c-yd)', border:'var(--c-y)' },
Active: { label:'Active', c:'var(--c-a)', bg:'var(--c-ad)', border:'var(--c-a)' },
Complete: { label:'Complete', c:'var(--c-g)', bg:'var(--c-gd)', border:'var(--c-g)' },
Cancelled: { label:'Cancelled', c:'var(--c-t3)', bg:'var(--c-surf2)', border:'var(--c-bd)' },
Disputed: { label:'Disputed', c:'var(--c-r)', bg:'var(--c-rd)', border:'var(--c-r)' },
};
return m[st] || { label: st, c:'var(--c-t3)', bg:'var(--c-surf2)', border:'var(--c-bd)' };
}
_av(n) {
if (n === 0) return { label:'Out of Stock', c:'var(--c-t3)', bg:'var(--c-surf2)', border:'var(--c-bd)' };
if (n <= 3) return { label:`Only ${n} left!`, c:'var(--c-y)', bg:'var(--c-yd)', border:'var(--c-y)' };
return { label:`${n} in stock`, c:'var(--c-g)', bg:'var(--c-gd)', border:'var(--c-g)' };
}
_fb(active) {
return active
? { bg:'var(--c-a)', c:'#fff', b:'var(--c-a)' }
: { bg:'transparent', c:'var(--c-t2)', b:'var(--c-bd)' };
}
renderVals() {
const s = this.state;
const L = this._L, R = this._R, O = this._O;
const listing = L[s.listingId] || L[0];
const resolver = R[s.resolverId] || R[0];
let prods = [...L];
if (s.stockFilter) prods = prods.filter(p => p.qty > 0);
if (s.curFilter !== 'all') prods = prods.filter(p => p.cur === s.curFilter);
if (s.search) {
const q = s.search.toLowerCase();
prods = prods.filter(p => p.name.toLowerCase().includes(q) || p.desc.toLowerCase().includes(q));
}
if (s.sort === 'priceLow') prods.sort((a,b) => a.priceNum - b.priceNum);
else if (s.sort === 'priceHigh') prods.sort((a,b) => b.priceNum - a.priceNum);
const la = this._av(listing.qty);
const fa = this._fb(s.curFilter === 'all');
const fs = this._fb(s.curFilter === 'SOL');
const fu = this._fb(s.curFilter === 'USDC');
const sn = this._fb(s.sort === 'newest');
const sl = this._fb(s.sort === 'priceLow');
const sh = this._fb(s.sort === 'priceHigh');
const lcp = this._fb(s.currency === listing.cur);
const lca = this._fb(s.currency === (listing.alt[0] || ''));
const od = (() => {
const o = O[s.orderId] || O[0];
const info = this._si(o.status);
const done2 = ['Active','Complete','Cancelled','Disputed'].includes(o.status);
const done3 = o.status === 'Complete';
return {
...o,
statusLabel: info.label,
sColor: info.c, sBg: info.bg, sBorder: info.border,
step12Bg: done2 ? 'var(--c-g)' : 'var(--c-bd2)',
step23Bg: done3 ? 'var(--c-g)' : 'var(--c-bd2)',
dot2Bg: done2 ? 'var(--c-g)' : o.status === 'AwaitingConfirm' ? 'var(--c-a)' : 'var(--c-surf2)',
dot2C: done2 ? '#000' : '#fff',
dot2Text: done2 ? '✓' : '2',
dot3Bg: done3 ? 'var(--c-g)' : o.status === 'Active' ? 'var(--c-a)' : 'var(--c-surf2)',
dot3C: done3 ? '#000' : '#fff',
dot3Text: done3 ? '✓' : '3',
s2Color: done2 ? 'var(--c-g)' : o.status === 'AwaitingConfirm' ? 'var(--c-a)' : 'var(--c-t3)',
s3Color: done3 ? 'var(--c-g)' : o.status === 'Active' ? 'var(--c-a)' : 'var(--c-t3)',
canCancel: o.status === 'AwaitingConfirm',
canConfirm: o.status === 'Active',
cancelOrder: () => { this._toast('Order cancelled. Full refund initiated.', 'success'); this.setState({ page: 'orders' }); },
confirmReceipt: () => { this._toast('Receipt confirmed! Seller has been paid.', 'success'); this.setState({ page: 'orders' }); },
goToListing: () => this.setState({ page: 'listing', listingId: o.lid }),
};
})();
return {
theme: s.theme,
toggleTheme: () => this.setState(st => ({ theme: st.theme === 'dark' ? 'light' : 'dark' })),
themeIcon: s.theme === 'dark' ? '☀' : '☽',
showHome: s.page === 'home',
showBrowse: s.page === 'browse',
showListing: s.page === 'listing',
showOrders: s.page === 'orders',
showOrderDetail: s.page === 'orderDetail',
showWalletModal: s.modal === 'wallet',
showCheckout: s.modal === 'checkout',
cReview: s.step === 'review',
cPending: s.step === 'pending',
cSuccess: s.step === 'success',
wallet: s.wallet,
notWallet: !s.wallet,
addr: s.addr,
walletOpen: s.walletOpen,
toggleWalletOpen: () => this.setState(st => ({ walletOpen: !st.walletOpen })),
goHome: () => this.setState({ page: 'home', modal: null, walletOpen: false }),
goBrowse: () => this.setState({ page: 'browse', modal: null, walletOpen: false }),
goOrders: () => this.setState({ page: 'orders', modal: null, walletOpen: false }),
openWalletModal: () => this.setState({ modal: 'wallet', walletOpen: false }),
closeModal: () => this.setState({ modal: null }),
stopProp: (e) => e.stopPropagation(),
disconnectWallet: () => { this.setState({ wallet: false, walletOpen: false }); this._toast('Wallet disconnected'); },
search: s.search,
onSearch: (e) => this.setState({ search: e.target.value, page: 'browse' }),
stockFilter: s.stockFilter,
toggleStock: () => this.setState(st => ({ stockFilter: !st.stockFilter })),
setFAll: () => this.setState({ curFilter: 'all' }),
setFSOL: () => this.setState({ curFilter: 'SOL' }),
setFUSDC: () => this.setState({ curFilter: 'USDC' }),
setSN: () => this.setState({ sort: 'newest' }),
setSL: () => this.setState({ sort: 'priceLow' }),
setSH: () => this.setState({ sort: 'priceHigh' }),
faBg:fa.bg, faC:fa.c, faB:fa.b,
fsBg:fs.bg, fsC:fs.c, fsB:fs.b,
fuBg:fu.bg, fuC:fu.c, fuB:fu.b,
snBg:sn.bg, snC:sn.c, snB:sn.b,
slBg:sl.bg, slC:sl.c, slB:sl.b,
shBg:sh.bg, shC:sh.c, shB:sh.b,
products: prods.map(p => {
const av = this._av(p.qty);
return {
...p,
availLabel: av.label, availC: av.c, availBg: av.bg, availBorder: av.border,
isOut: p.qty === 0,
buyLabel: p.qty === 0 ? 'Out of Stock' : 'Buy Now',
buyBg: p.qty === 0 ? 'var(--c-surf2)' : 'var(--c-a)',
buyC: p.qty === 0 ? 'var(--c-t3)' : '#fff',
buyCursor: p.qty === 0 ? 'not-allowed' : 'pointer',
hasAlt: p.alt.length > 0,
altLabel: p.alt.join(' · '),
priceVal: String(p.priceNum),
showAvailBadge: p.qty === 0 || p.qty <= 3,
clickCard: () => this.setState({ page: 'listing', listingId: p.id, currency: p.cur }),
clickBuy: (e) => {
e.stopPropagation();
if (p.qty === 0) return;
this.setState({ listingId: p.id, currency: p.cur });
if (!s.wallet) this.setState({ modal: 'wallet', pendingId: p.id });
else this.setState({ page: 'listing', modal: 'checkout', step: 'review' });
},
};
}),
listing,
lAvailLabel: la.label, lAvailC: la.c, lAvailBg: la.bg, lAvailBorder: la.border,
lIsOut: listing.qty === 0,
lHasAlt: listing.alt.length > 0,
lCurPrimary: listing.cur,
lCurAlt: listing.alt[0] || '',
lcpBg:lcp.bg, lcpC:lcp.c, lcpB:lcp.b,
lcaBg:lca.bg, lcaC:lca.c, lcaB:lca.b,
lSetCurPrimary: () => this.setState({ currency: listing.cur }),
lSetCurAlt: () => this.setState({ currency: listing.alt[0] || listing.cur }),
lBuyLabel: listing.qty === 0 ? 'Out of Stock' : s.wallet ? 'Buy Now →' : 'Connect Wallet to Buy',
lBuyBg: listing.qty === 0 ? 'var(--c-surf2)' : 'var(--c-a)',
lBuyC: listing.qty === 0 ? 'var(--c-t3)' : '#fff',
lBuyCursor: listing.qty === 0 ? 'not-allowed' : 'pointer',
goBack: () => this.setState({ page: 'browse' }),
onBuyNow: () => {
if (listing.qty === 0) return;
if (!s.wallet) this.setState({ modal: 'wallet', pendingId: listing.id });
else this.setState({ modal: 'checkout', step: 'review' });
},
copySeller: () => { navigator.clipboard.writeText(listing.seller).catch(()=>{}); this._toast('Address copied!'); },
resolvers: R.map(r => {
const sel = r.id === s.resolverId;
return {
...r,
isSelected: sel,
rBg: sel ? 'var(--c-ad)' : 'transparent',
rBorder: sel ? 'var(--c-a)' : 'var(--c-bd)',
rNameC: sel ? 'var(--c-a)' : 'var(--c-t)',
selectIt: () => this.setState({ resolverId: r.id }),
};
}),
resolver,
cListing: listing,
cAmount: listing.price,
cUsd: listing.usd,
cResolver: resolver,
confirmOrder: () => {
this.setState({ step: 'pending' });
setTimeout(() => this.setState({ step: 'success' }), 2200);
},
viewOrders: () => this.setState({ modal: null, page: 'orders' }),
continueShopping: () => this.setState({ modal: null, page: 'browse' }),
connectPhantom: () => {
const pid = this.state.pendingId;
this.setState({ wallet: true, addr: 'Gh9Z…k3mP' });
if (pid !== null) this.setState({ modal: 'checkout', step: 'review', listingId: pid, pendingId: null });
else this.setState({ modal: null });
this._toast('Phantom connected!', 'success');
},
connectSolflare: () => {
const pid = this.state.pendingId;
this.setState({ wallet: true, addr: 'Bx3K…7pRq' });
if (pid !== null) this.setState({ modal: 'checkout', step: 'review', listingId: pid, pendingId: null });
else this.setState({ modal: null });
this._toast('Solflare connected!', 'success');
},
connectBackpack: () => {
const pid = this.state.pendingId;
this.setState({ wallet: true, addr: 'Kx7P…2mJc' });
if (pid !== null) this.setState({ modal: 'checkout', step: 'review', listingId: pid, pendingId: null });
else this.setState({ modal: null });
this._toast('Backpack connected!', 'success');
},
toastVisible: !!s.toast,
toastMsg: s.toast || '',
toastBg: s.toastType==='success' ? 'var(--c-gd)' : s.toastType==='error' ? 'var(--c-rd)' : 'var(--c-surf2)',
toastC: s.toastType==='success' ? 'var(--c-g)' : s.toastType==='error' ? 'var(--c-r)' : 'var(--c-t)',
toastBorder: s.toastType==='success' ? 'var(--c-g)' : s.toastType==='error' ? 'var(--c-r)' : 'var(--c-bd2)',
orders: O.map(o => {
const info = this._si(o.status);
return { ...o, statusLabel: info.label, sColor: info.c, sBg: info.bg, sBorder: info.border,
clickOrder: () => this.setState({ page: 'orderDetail', orderId: o.id }) };
}),
od,
goBackOrders: () => this.setState({ page: 'orders' }),
featuredProducts: L.filter(p => p.qty > 0).slice(0, 4).map(p => ({
...p,
priceVal: String(p.priceNum),
clickCard: () => this.setState({ page: 'listing', listingId: p.id, currency: p.cur }),
})),
viewMode: s.viewMode,
isListView: s.viewMode === 'list',
isGridView: s.viewMode === 'grid',
setViewList: () => this.setState({ viewMode: 'list' }),
setViewGrid: () => this.setState({ viewMode: 'grid' }),
vlBg: this._fb(s.viewMode === 'list'),
vgBg: this._fb(s.viewMode === 'grid'),
relatedProducts: L.filter(l => l.id !== s.listingId && l.qty > 0).slice(0, 6).map(p => ({
...p,
clickCard: () => this.setState({ page: 'listing', listingId: p.id, currency: p.cur }),
})),
};
}
}
</script>
</body>
</html>