1123 lines
80 KiB
HTML
1123 lines
80 KiB
HTML
<!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;"><$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.5–1.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 & 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 & 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;">◎ <$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 & 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 & 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 24–48h</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="{
|
||
"$preview": {"width": 1440, "height": 900},
|
||
"initialTheme": {"editor": "enum", "options": ["dark", "light"], "default": "dark", "section": "Appearance"},
|
||
"accentColor": {"editor": "color", "default": "#9945ff", "section": "Appearance"}
|
||
}">
|
||
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>
|