Web3 — Crypto Exchange (CEX) Landing
A data-dense, trustworthy landing page for a fictional crypto exchange, Vaultex, built with HTML, CSS and vanilla JavaScript. It pairs a conversion-focused hero and email capture with a live markets widget — an animated ticker tape, a sortable top-pairs table with sparklines and live-ish price jitter, and count-up stats. Sections cover a Spot, Futures and Earn feature trio, a security and regulation trust band with an insurance fund, a fees comparison strip, a supported-assets logo wall, and an app download CTA with an animated phone mockup.
MCP
Code
/* Vaultex — Crypto Exchange (CEX) Landing · UI-only simulation */
:root {
--bg: #070a0d;
--surface: #0e1318;
--surface-2: #131a21;
--elevated: #1a232c;
--text: #eaf0f6;
--muted: #8b96a5;
--line: rgba(255, 255, 255, 0.07);
--line-2: rgba(255, 255, 255, 0.15);
--accent: #f0b90b;
--accent-2: #f8d33a;
--accent-glow: rgba(240, 185, 11, 0.35);
--pos: #16c784;
--neg: #ea3943;
--warn: #ffb347;
--pos-bg: rgba(22, 199, 132, 0.12);
--neg-bg: rgba(234, 57, 67, 0.12);
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
--r-pill: 999px;
--font-ui: "Space Grotesk", system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
margin: 0;
font-family: var(--font-ui);
font-size: 16px;
line-height: 1.5;
color: var(--text);
background: var(--bg);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
.mono {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
.pos { color: var(--pos); }
.neg { color: var(--neg); }
.gold-text {
background: linear-gradient(100deg, var(--accent) 10%, var(--accent-2) 60%, #fff3c4 95%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.container {
width: min(1180px, 100% - 40px);
margin-inline: auto;
}
.section {
padding: 84px 0;
}
.section-title {
margin: 0 0 8px;
font-size: clamp(26px, 3.4vw, 38px);
font-weight: 700;
letter-spacing: -0.02em;
text-align: center;
}
.section-sub {
margin: 0 auto 40px;
max-width: 560px;
text-align: center;
color: var(--muted);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
border: 0;
}
/* ===== Buttons ===== */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 18px;
border: 1px solid transparent;
border-radius: var(--r-sm);
font: 600 14px/1.2 var(--font-ui);
color: var(--text);
background: var(--surface-2);
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:focus-visible,
.tab:focus-visible,
.sort-btn:focus-visible,
.card-link:focus-visible,
a:focus-visible,
.email-input:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: var(--r-sm);
}
.btn-gold {
background: linear-gradient(135deg, var(--accent), var(--accent-2));
color: #1a1303;
box-shadow: 0 6px 22px -6px var(--accent-glow);
}
.btn-gold:hover {
box-shadow: 0 10px 30px -6px var(--accent-glow);
filter: brightness(1.05);
}
.btn-ghost {
background: transparent;
border-color: var(--line-2);
}
.btn-ghost:hover {
border-color: var(--accent);
color: var(--accent);
}
.btn-lg {
padding: 14px 24px;
font-size: 15px;
}
/* ===== Header ===== */
.site-header {
position: sticky;
top: 0;
z-index: 50;
background: rgba(7, 10, 13, 0.82);
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
border-bottom: 1px solid var(--line);
}
.header-inner {
display: flex;
align-items: center;
gap: 28px;
height: 64px;
}
.logo {
display: inline-flex;
align-items: center;
gap: 10px;
text-decoration: none;
color: var(--text);
}
.logo-mark {
display: grid;
place-items: center;
width: 32px;
height: 32px;
border-radius: var(--r-sm);
background: linear-gradient(135deg, var(--accent), var(--accent-2));
color: #1a1303;
font-weight: 700;
font-size: 18px;
box-shadow: 0 4px 16px -4px var(--accent-glow);
}
.logo-word {
font-size: 19px;
font-weight: 700;
letter-spacing: -0.01em;
}
.main-nav {
display: flex;
gap: 4px;
margin-right: auto;
}
.main-nav a {
padding: 8px 12px;
border-radius: var(--r-sm);
font-size: 14px;
font-weight: 500;
color: var(--muted);
text-decoration: none;
transition: color 0.15s, background 0.15s;
}
.main-nav a:hover {
color: var(--text);
background: var(--surface-2);
}
.header-actions {
display: flex;
gap: 10px;
margin-left: auto;
}
/* ===== Ticker tape ===== */
.ticker {
overflow: hidden;
border-bottom: 1px solid var(--line);
background: var(--surface);
-webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.ticker-track {
display: flex;
width: max-content;
animation: ticker-scroll 38s linear infinite;
}
.ticker:hover .ticker-track {
animation-play-state: paused;
}
@keyframes ticker-scroll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
.ticker-item {
display: inline-flex;
align-items: baseline;
gap: 8px;
padding: 9px 22px;
border-right: 1px solid var(--line);
font-size: 13px;
white-space: nowrap;
}
.ticker-item .sym {
font-weight: 600;
letter-spacing: 0.02em;
}
.ticker-item .px,
.ticker-item .chg {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
.ticker-item .px { color: var(--muted); }
/* ===== Hero ===== */
.hero {
position: relative;
padding: 72px 0 84px;
overflow: hidden;
}
.hero::before {
content: "";
position: absolute;
inset: -40% -20% auto;
height: 90%;
background:
radial-gradient(46% 60% at 24% 30%, rgba(240, 185, 11, 0.13), transparent 70%),
radial-gradient(40% 55% at 80% 18%, rgba(22, 199, 132, 0.08), transparent 70%);
pointer-events: none;
}
.hero-grid {
position: relative;
display: grid;
grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
gap: 56px;
align-items: start;
}
.hero-eyebrow {
display: inline-flex;
align-items: center;
gap: 8px;
margin: 0 0 18px;
padding: 6px 14px;
border: 1px solid var(--line-2);
border-radius: var(--r-pill);
background: rgba(255, 255, 255, 0.03);
font-size: 13px;
font-weight: 500;
color: var(--muted);
}
.live-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--pos);
box-shadow: 0 0 0 0 rgba(22, 199, 132, 0.6);
animation: pulse 2s ease-out infinite;
}
@keyframes pulse {
70% { box-shadow: 0 0 0 7px rgba(22, 199, 132, 0); }
100% { box-shadow: 0 0 0 0 rgba(22, 199, 132, 0); }
}
.hero h1 {
margin: 0 0 16px;
font-size: clamp(34px, 4.6vw, 56px);
font-weight: 700;
line-height: 1.08;
letter-spacing: -0.025em;
}
.hero-sub {
margin: 0 0 28px;
max-width: 480px;
font-size: 17px;
color: var(--muted);
}
.signup-form {
display: flex;
gap: 10px;
max-width: 480px;
}
.email-input {
flex: 1;
min-width: 0;
padding: 13px 16px;
border: 1px solid var(--line-2);
border-radius: var(--r-sm);
background: var(--surface);
color: var(--text);
font: 500 15px var(--font-ui);
transition: border-color 0.2s, box-shadow 0.2s;
}
.email-input::placeholder { color: var(--muted); }
.email-input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(240, 185, 11, 0.18);
outline: none;
}
.email-input.is-invalid {
border-color: var(--neg);
box-shadow: 0 0 0 3px rgba(234, 57, 67, 0.18);
}
.form-hint {
margin: 10px 0 0;
font-size: 13px;
color: var(--muted);
}
.form-hint strong { color: var(--accent); }
.form-hint.is-error { color: var(--neg); }
.form-hint.is-success { color: var(--pos); }
.hero-stats {
display: grid;
grid-template-columns: repeat(4, auto);
gap: 14px 36px;
margin: 40px 0 0;
padding-top: 28px;
border-top: 1px solid var(--line);
}
.stat dt {
font-size: 12px;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--muted);
}
.stat dd {
margin: 4px 0 0;
}
.stat .num {
font-family: var(--font-mono);
font-size: 22px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
/* ===== Markets widget ===== */
.markets-card {
position: relative;
border: 1px solid var(--line);
border-radius: var(--r-lg);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.01)), var(--surface);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.7);
padding: 20px 20px 14px;
scroll-margin-top: 90px;
}
.markets-card::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
background: linear-gradient(135deg, rgba(240, 185, 11, 0.5), transparent 35%, transparent 70%, rgba(22, 199, 132, 0.35));
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
.markets-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 12px;
}
.markets-head h2 {
display: flex;
align-items: center;
gap: 10px;
margin: 0;
font-size: 18px;
font-weight: 700;
}
.live-pill {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 3px 10px;
border-radius: var(--r-pill);
background: var(--pos-bg);
color: var(--pos);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.tabs {
display: flex;
gap: 4px;
padding: 3px;
border: 1px solid var(--line);
border-radius: var(--r-pill);
background: var(--surface-2);
}
.tab {
padding: 5px 14px;
border: 0;
border-radius: var(--r-pill);
background: transparent;
color: var(--muted);
font: 600 13px var(--font-ui);
cursor: pointer;
transition: color 0.15s, background 0.15s;
}
.tab:hover { color: var(--text); }
.tab.is-active {
background: var(--elevated);
color: var(--accent);
}
.table-wrap {
overflow-x: auto;
}
.markets-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.markets-table th,
.markets-table td {
padding: 9px 10px;
text-align: left;
white-space: nowrap;
}
.markets-table thead th {
border-bottom: 1px solid var(--line);
font-size: 12px;
font-weight: 600;
color: var(--muted);
}
.num-col,
.markets-table td.num-cell {
text-align: right;
}
.sort-btn {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 4px;
border: 0;
background: none;
color: inherit;
font: inherit;
cursor: pointer;
border-radius: 4px;
}
.sort-btn:hover { color: var(--text); }
.sort-arrow::after {
content: "↕";
font-size: 10px;
opacity: 0.55;
}
th[aria-sort="ascending"] .sort-arrow::after { content: "↑"; opacity: 1; color: var(--accent); }
th[aria-sort="descending"] .sort-arrow::after { content: "↓"; opacity: 1; color: var(--accent); }
.markets-table tbody tr {
border-bottom: 1px solid var(--line);
transition: background 0.15s;
}
.markets-table tbody tr:last-child { border-bottom: 0; }
.markets-table tbody tr:hover {
background: rgba(255, 255, 255, 0.03);
}
.pair-cell {
display: flex;
align-items: center;
gap: 10px;
}
.coin-dot {
display: grid;
place-items: center;
width: 28px;
height: 28px;
flex: 0 0 28px;
border-radius: 50%;
background: color-mix(in srgb, var(--c, var(--accent)) 18%, transparent);
border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 55%, transparent);
color: var(--c, var(--accent));
font: 700 12px var(--font-ui);
}
.pair-name {
display: flex;
flex-direction: column;
line-height: 1.2;
}
.pair-name b { font-weight: 600; }
.pair-name small {
font-size: 11px;
color: var(--muted);
}
.pair-name .quote { color: var(--muted); font-weight: 400; }
.price-cell,
.vol-cell {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
.chg-pill {
display: inline-block;
min-width: 72px;
padding: 3px 8px;
border-radius: var(--r-sm);
font-family: var(--font-mono);
font-size: 13px;
font-weight: 500;
text-align: right;
font-variant-numeric: tabular-nums;
}
.chg-pill.pos { background: var(--pos-bg); }
.chg-pill.neg { background: var(--neg-bg); }
.spark { display: block; }
.trade-btn {
padding: 5px 14px;
border: 1px solid var(--line-2);
border-radius: var(--r-sm);
background: transparent;
color: var(--text);
font: 600 12px var(--font-ui);
cursor: pointer;
transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.trade-btn:hover {
border-color: var(--accent);
color: #1a1303;
background: var(--accent);
}
/* price flash on jitter */
@keyframes flash-up {
0% { background: rgba(22, 199, 132, 0.22); }
100% { background: transparent; }
}
@keyframes flash-down {
0% { background: rgba(234, 57, 67, 0.22); }
100% { background: transparent; }
}
td.flash-up { animation: flash-up 0.9s ease-out; }
td.flash-down { animation: flash-down 0.9s ease-out; }
.price-cell.up { color: var(--pos); }
.price-cell.down { color: var(--neg); }
.markets-note {
margin: 10px 2px 0;
font-size: 12px;
color: var(--muted);
}
/* ===== Features ===== */
.feature-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.feature-card {
display: flex;
flex-direction: column;
gap: 12px;
padding: 28px 26px;
border: 1px solid var(--line);
border-radius: var(--r-lg);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent 60%), var(--surface);
transition: transform 0.2s ease, border-color 0.2s, box-shadow 0.25s;
}
.feature-card:hover {
transform: translateY(-4px);
border-color: rgba(240, 185, 11, 0.4);
box-shadow: 0 18px 40px -22px var(--accent-glow);
}
.feature-icon {
display: grid;
place-items: center;
width: 50px;
height: 50px;
border-radius: var(--r-md);
background: rgba(240, 185, 11, 0.1);
border: 1px solid rgba(240, 185, 11, 0.3);
color: var(--accent);
}
.feature-card h3 {
margin: 0;
font-size: 20px;
font-weight: 700;
}
.feature-card p {
margin: 0;
flex: 1;
font-size: 14.5px;
color: var(--muted);
}
.risk-tag {
align-self: flex-start;
padding: 4px 10px;
border-radius: var(--r-sm);
background: rgba(255, 179, 71, 0.12);
border: 1px solid rgba(255, 179, 71, 0.35);
color: var(--warn);
font-size: 12px;
font-weight: 500;
}
.card-link {
align-self: flex-start;
padding: 4px 2px;
border: 0;
background: none;
color: var(--accent);
font: 600 14px var(--font-ui);
cursor: pointer;
transition: color 0.15s;
}
.card-link:hover { color: var(--accent-2); }
/* ===== Trust band ===== */
.trust-band {
display: grid;
grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr);
gap: 40px;
align-items: center;
padding: 44px 46px;
border: 1px solid var(--line);
border-radius: var(--r-lg);
background:
radial-gradient(60% 120% at 0% 0%, rgba(240, 185, 11, 0.1), transparent 60%),
var(--surface);
}
.trust-headline h2 {
margin: 0 0 12px;
font-size: clamp(24px, 2.8vw, 32px);
letter-spacing: -0.02em;
}
.trust-headline p {
margin: 0;
color: var(--muted);
font-size: 15px;
}
.big-num {
display: block;
font-size: clamp(34px, 4vw, 48px);
font-weight: 700;
line-height: 1.1;
margin-bottom: 4px;
}
.trust-badges {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 18px;
margin: 0;
padding: 0;
list-style: none;
}
.trust-badges li {
display: flex;
gap: 12px;
align-items: flex-start;
padding: 16px;
border: 1px solid var(--line);
border-radius: var(--r-md);
background: rgba(255, 255, 255, 0.025);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
}
.badge-icon {
display: grid;
place-items: center;
width: 34px;
height: 34px;
flex: 0 0 34px;
border-radius: 50%;
background: rgba(22, 199, 132, 0.12);
border: 1px solid rgba(22, 199, 132, 0.4);
color: var(--pos);
font-size: 15px;
}
.trust-badges strong {
display: block;
font-size: 14.5px;
}
.trust-badges span:not(.badge-icon) {
font-size: 12.5px;
color: var(--muted);
}
/* ===== Fees ===== */
.fees .table-wrap {
max-width: 760px;
margin: 0 auto;
border: 1px solid var(--line);
border-radius: var(--r-lg);
background: var(--surface);
}
.fees-table {
width: 100%;
border-collapse: collapse;
font-size: 14.5px;
}
.fees-table th,
.fees-table td {
padding: 14px 20px;
text-align: center;
border-bottom: 1px solid var(--line);
}
.fees-table tbody tr:last-child th,
.fees-table tbody tr:last-child td {
border-bottom: 0;
}
.fees-table thead th {
font-size: 13px;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--muted);
}
.fees-table tbody th {
text-align: left;
font-weight: 500;
color: var(--muted);
}
.fees-table .fees-us {
background: rgba(240, 185, 11, 0.07);
color: var(--accent);
font-weight: 700;
}
.fees-table thead .fees-us {
color: var(--accent);
font-size: 14px;
}
.fees-note {
margin: 14px auto 0;
max-width: 760px;
text-align: center;
font-size: 12.5px;
color: var(--muted);
}
/* ===== Asset wall ===== */
.asset-wall {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 14px;
margin: 0;
padding: 0;
list-style: none;
}
.asset-wall li {
display: flex;
align-items: center;
gap: 10px;
padding: 14px 16px;
border: 1px solid var(--line);
border-radius: var(--r-md);
background: var(--surface);
transition: transform 0.18s ease, border-color 0.18s, background 0.18s;
}
.asset-wall li:hover {
transform: translateY(-3px);
border-color: var(--line-2);
background: var(--surface-2);
}
.asset-wall .asset-name {
display: flex;
flex-direction: column;
line-height: 1.2;
min-width: 0;
}
.asset-wall .asset-name b {
font-size: 13.5px;
font-weight: 600;
}
.asset-wall .asset-name small {
font-size: 11px;
color: var(--muted);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ===== App CTA ===== */
.app-cta {
position: relative;
overflow: hidden;
}
.app-grid {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
gap: 48px;
align-items: center;
padding: 56px 52px;
border: 1px solid var(--line);
border-radius: var(--r-lg);
background:
radial-gradient(70% 130% at 100% 0%, rgba(240, 185, 11, 0.1), transparent 55%),
var(--surface);
}
.app-copy h2 {
margin: 0 0 12px;
font-size: clamp(26px, 3vw, 36px);
letter-spacing: -0.02em;
}
.app-copy > p {
margin: 0 0 26px;
color: var(--muted);
max-width: 420px;
}
.store-buttons {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.store-btn {
gap: 12px;
padding: 10px 20px;
border: 1px solid var(--line-2);
background: var(--surface-2);
text-align: left;
}
.store-btn:hover {
border-color: var(--accent);
background: var(--elevated);
}
.store-icon {
display: inline-grid;
place-items: center;
width: 26px;
height: 26px;
border-radius: 7px;
background: var(--elevated);
color: var(--accent);
font-size: 12px;
}
.store-icon:not(.play)::after { content: "⌘"; font-size: 15px; }
.store-text { display: inline-flex; flex-direction: column; line-height: 1.25; }
.store-text small {
font-size: 10.5px;
font-weight: 500;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.qr-hint {
display: flex;
align-items: center;
gap: 12px;
margin: 24px 0 0;
font-size: 13px;
color: var(--muted);
}
.qr-box {
width: 46px;
height: 46px;
flex: 0 0 46px;
border-radius: var(--r-sm);
background:
repeating-conic-gradient(var(--text) 0% 25%, var(--surface) 0% 50%) 0 0 / 12px 12px;
border: 4px solid #fff;
opacity: 0.85;
}
/* Phone mockup */
.phone-wrap {
position: relative;
display: flex;
justify-content: center;
}
.phone {
position: relative;
z-index: 1;
width: 260px;
border-radius: 36px;
border: 1px solid var(--line-2);
background: #0b0f13;
padding: 10px;
box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.8);
}
.phone-glow {
position: absolute;
inset: 12% 18%;
background: radial-gradient(closest-side, var(--accent-glow), transparent 75%);
filter: blur(28px);
opacity: 0.55;
pointer-events: none;
}
.phone-notch {
position: absolute;
top: 14px;
left: 50%;
transform: translateX(-50%);
width: 84px;
height: 18px;
border-radius: var(--r-pill);
background: #05070a;
z-index: 2;
}
.phone-screen {
display: flex;
flex-direction: column;
gap: 12px;
border-radius: 28px;
background: linear-gradient(180deg, #10161c, #0a0e12);
padding: 44px 16px 16px;
min-height: 440px;
}
.phone-row { display: flex; flex-direction: column; }
.phone-label {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted);
}
.phone-amount {
font-size: 24px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.phone-pnl { font-size: 11.5px; }
.phone-chart {
display: flex;
align-items: flex-end;
gap: 4px;
height: 84px;
padding: 8px;
border-radius: var(--r-md);
background: rgba(255, 255, 255, 0.03);
border: 1px solid var(--line);
}
.phone-chart .bar {
flex: 1;
border-radius: 3px 3px 0 0;
background: linear-gradient(180deg, var(--pos), rgba(22, 199, 132, 0.25));
min-height: 8%;
transition: height 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.phone-chart .bar.down {
background: linear-gradient(180deg, var(--neg), rgba(234, 57, 67, 0.25));
}
.phone-asset {
flex-direction: row;
align-items: center;
gap: 10px;
padding: 10px 12px;
border-radius: var(--r-md);
background: rgba(255, 255, 255, 0.035);
border: 1px solid var(--line);
font-size: 13px;
}
.phone-asset-name {
display: flex;
flex-direction: column;
line-height: 1.2;
font-weight: 600;
}
.phone-asset-name small {
font-weight: 400;
font-size: 10.5px;
color: var(--muted);
}
.phone-asset-val {
margin-left: auto;
display: flex;
flex-direction: column;
align-items: flex-end;
line-height: 1.25;
font-size: 13px;
}
.phone-asset-val small { font-size: 10.5px; }
.phone-actions {
display: flex;
gap: 10px;
margin-top: auto;
}
.phone-btn {
flex: 1;
padding: 10px;
border-radius: var(--r-sm);
text-align: center;
font-size: 13px;
font-weight: 700;
background: linear-gradient(135deg, var(--accent), var(--accent-2));
color: #1a1303;
}
.phone-btn.alt {
background: var(--surface-2);
color: var(--text);
border: 1px solid var(--line-2);
}
/* ===== Footer ===== */
.site-footer {
margin-top: 40px;
border-top: 1px solid var(--line);
background: var(--surface);
}
.footer-grid {
display: grid;
grid-template-columns: 1.4fr 1fr 1fr 1fr;
gap: 36px;
padding: 56px 0 36px;
}
.footer-brand p {
margin: 14px 0 0;
max-width: 280px;
font-size: 13.5px;
color: var(--muted);
}
.footer-addr {
font-size: 12.5px;
color: var(--accent);
}
.site-footer h3 {
margin: 0 0 14px;
font-size: 13px;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--muted);
}
.site-footer nav a {
display: block;
padding: 5px 0;
font-size: 14px;
color: var(--text);
text-decoration: none;
opacity: 0.85;
transition: color 0.15s, opacity 0.15s;
}
.site-footer nav a:hover {
color: var(--accent);
opacity: 1;
}
.footer-legal {
padding: 18px 20px 26px;
border-top: 1px solid var(--line);
}
.footer-legal p {
margin: 0;
font-size: 12px;
color: var(--muted);
}
/* ===== Toast ===== */
.toast {
position: fixed;
left: 50%;
bottom: 28px;
z-index: 100;
transform: translate(-50%, 16px);
max-width: min(420px, calc(100vw - 40px));
padding: 12px 20px;
border-radius: var(--r-md);
border: 1px solid var(--line-2);
background: rgba(26, 35, 44, 0.92);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.7);
color: var(--text);
font-size: 14px;
font-weight: 500;
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease, transform 0.25s ease;
}
.toast.is-visible {
opacity: 1;
transform: translate(-50%, 0);
}
/* ===== Responsive ===== */
@media (max-width: 980px) {
.hero-grid { grid-template-columns: 1fr; gap: 44px; }
.hero-stats { grid-template-columns: repeat(2, auto); }
.feature-grid { grid-template-columns: 1fr; }
.trust-band { grid-template-columns: 1fr; padding: 34px 28px; }
.asset-wall { grid-template-columns: repeat(3, 1fr); }
.app-grid { grid-template-columns: 1fr; padding: 40px 28px; }
.footer-grid { grid-template-columns: 1fr 1fr; }
.main-nav { display: none; }
}
@media (max-width: 520px) {
.container { width: calc(100% - 28px); }
.section { padding: 56px 0; }
.header-inner { gap: 12px; }
.btn-ghost { display: none; }
.hero { padding: 48px 0 60px; }
.signup-form { flex-direction: column; }
.signup-form .btn { width: 100%; }
.hero-stats { gap: 14px 22px; }
.stat .num { font-size: 18px; }
.markets-card { padding: 14px 12px 10px; }
.markets-table th,
.markets-table td { padding: 8px 6px; }
.hide-sm { display: none; }
.chg-pill { min-width: 64px; font-size: 12px; }
.trust-badges { grid-template-columns: 1fr; }
.asset-wall { grid-template-columns: repeat(2, 1fr); }
.fees-table th,
.fees-table td { padding: 11px 10px; font-size: 13px; }
.footer-grid { grid-template-columns: 1fr; gap: 26px; padding: 40px 0 26px; }
.phone { width: 230px; }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.ticker-track { animation-duration: 120s; }
.live-dot { animation: none; }
*,
*::before,
*::after { transition-duration: 0.01ms !important; }
}/* Vaultex — Crypto Exchange (CEX) landing.
UI-only simulation: mock data, fictional tokens, no real trading or network calls. */
(function () {
"use strict";
var fmtUSD = function (n, dp) {
if (dp == null) dp = n >= 1000 ? 2 : n >= 1 ? 3 : 5;
return "$" + n.toLocaleString("en-US", { minimumFractionDigits: dp, maximumFractionDigits: dp });
};
var fmtPct = function (n) { return (n >= 0 ? "+" : "") + n.toFixed(2) + "%"; };
var fmtVol = function (n) {
if (n >= 1e9) return "$" + (n / 1e9).toFixed(1) + "B";
if (n >= 1e6) return "$" + (n / 1e6).toFixed(1) + "M";
return "$" + Math.round(n).toLocaleString("en-US");
};
/* ---------- Mock market data (fictional assets) ---------- */
var COINS = [
{ sym: "NOVA", name: "Novabit", c: "#f0b90b", price: 0.2841, change: 2.31, vol: 4.82e9 },
{ sym: "LMN", name: "Lumen", c: "#16c784", price: 142.50, change: -1.12, vol: 2.14e9 },
{ sym: "ZEPH", name: "Zephyr", c: "#7c5cff", price: 18.337, change: 5.74, vol: 1.96e9 },
{ sym: "ORBT", name: "Orbital", c: "#00e0c6", price: 1.0042, change: 0.04, vol: 3.51e9 },
{ sym: "FLUX", name: "Fluxchain", c: "#ff9f1c", price: 0.00734, change: -3.88, vol: 880e6 },
{ sym: "AXON", name: "Axon", c: "#ff4d6d", price: 64.218, change: 1.47, vol: 1.22e9 },
{ sym: "QUBE", name: "Qubit", c: "#4ea8ff", price: 9.6051, change: 8.02, vol: 760e6 },
{ sym: "HELO", name: "Helios", c: "#ffd23f", price: 3.2218, change: -0.63, vol: 540e6 }
];
COINS.forEach(function (c) { c.spark = makeSpark(c.change); });
function makeSpark(bias) {
var pts = [], v = 50;
for (var i = 0; i < 24; i++) {
v += (Math.random() - 0.5) * 14 + bias * 0.18;
v = Math.max(10, Math.min(90, v));
pts.push(v);
}
return pts;
}
function sparkSVG(pts, up) {
var w = 88, h = 28, max = Math.max.apply(null, pts), min = Math.min.apply(null, pts);
var rng = max - min || 1;
var d = pts.map(function (p, i) {
var x = (i / (pts.length - 1)) * w;
var y = h - ((p - min) / rng) * (h - 4) - 2;
return (i ? "L" : "M") + x.toFixed(1) + " " + y.toFixed(1);
}).join(" ");
var col = up ? "var(--pos)" : "var(--neg)";
return '<svg class="spark" width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + " " + h +
'" fill="none" aria-hidden="true"><path d="' + d + '" stroke="' + col +
'" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
}
/* ---------- Ticker tape ---------- */
(function ticker() {
var track = document.getElementById("tickerTrack");
if (!track) return;
function itemHTML(c) {
var up = c.change >= 0;
return '<span class="ticker-item"><span class="sym">' + c.sym +
'</span><span class="px">' + fmtUSD(c.price) +
'</span><span class="chg ' + (up ? "pos" : "neg") + '">' + fmtPct(c.change) + "</span></span>";
}
// duplicate the set so the CSS marquee loops seamlessly
var html = COINS.map(itemHTML).join("");
track.innerHTML = html + html;
})();
/* ---------- Markets table ---------- */
var tbody = document.getElementById("marketsBody");
var sortKey = "vol", sortDir = -1, filter = "all";
function rowHTML(c) {
var up = c.change >= 0;
return '<tr data-sym="' + c.sym + '">' +
'<td><div class="pair-name-wrap" style="display:flex;align-items:center;gap:10px">' +
'<span class="coin-dot" style="--c:' + c.c + '">' + c.sym.charAt(0) + '</span>' +
'<span class="pair-name"><b>' + c.sym + '<span class="quote"> / USDQ</span></b>' +
'<small>' + c.name + '</small></span></div></td>' +
'<td class="num-cell price-cell">' + fmtUSD(c.price) + '</td>' +
'<td class="num-cell"><span class="chg-pill ' + (up ? "pos" : "neg") + '">' + fmtPct(c.change) + '</span></td>' +
'<td class="num-cell vol-cell hide-sm">' + fmtVol(c.vol) + '</td>' +
'<td class="spark-col hide-sm">' + sparkSVG(c.spark, up) + '</td>' +
'<td class="action-col"><button class="trade-btn" type="button" data-trade="' + c.sym + '">Trade</button></td>' +
'</tr>';
}
function visibleCoins() {
return COINS.filter(function (c) {
if (filter === "gainers") return c.change >= 0;
if (filter === "losers") return c.change < 0;
return true;
});
}
function sortedCoins() {
var arr = visibleCoins().slice();
arr.sort(function (a, b) {
var x, y;
if (sortKey === "sym") { x = a.sym; y = b.sym; return x < y ? -sortDir : x > y ? sortDir : 0; }
if (sortKey === "price") { x = a.price; y = b.price; }
else if (sortKey === "change") { x = a.change; y = b.change; }
else { x = a.vol; y = b.vol; }
return (x - y) * sortDir;
});
return arr;
}
function renderTable() {
if (!tbody) return;
tbody.innerHTML = sortedCoins().map(rowHTML).join("");
}
renderTable();
// Sort handlers
Array.prototype.forEach.call(document.querySelectorAll(".sort-btn"), function (btn) {
btn.addEventListener("click", function () {
var key = btn.getAttribute("data-sort");
if (key === sortKey) sortDir = -sortDir;
else { sortKey = key; sortDir = key === "sym" ? 1 : -1; }
// reset aria-sort on all headers, set on this one
Array.prototype.forEach.call(document.querySelectorAll(".markets-table th"), function (th) {
th.setAttribute("aria-sort", "none");
});
var th = btn.closest("th");
if (th) th.setAttribute("aria-sort", sortDir === 1 ? "ascending" : "descending");
renderTable();
});
});
// Filter tabs
Array.prototype.forEach.call(document.querySelectorAll(".tab"), function (tab) {
tab.addEventListener("click", function () {
filter = tab.getAttribute("data-filter");
Array.prototype.forEach.call(document.querySelectorAll(".tab"), function (t) {
t.classList.toggle("is-active", t === tab);
t.setAttribute("aria-selected", t === tab ? "true" : "false");
});
renderTable();
});
});
// Trade button -> toast (no real trading)
if (tbody) {
tbody.addEventListener("click", function (e) {
var b = e.target.closest("[data-trade]");
if (b) toast("Order ticket for " + b.getAttribute("data-trade") + "/USDQ is simulated — no trade is placed.");
});
}
/* ---------- Live-ish price jitter ---------- */
function jitter() {
var changed = COINS[Math.floor(Math.random() * COINS.length)];
var n = 1 + Math.floor(Math.random() * 3);
for (var k = 0; k < n; k++) {
var c = COINS[Math.floor(Math.random() * COINS.length)];
var delta = (Math.random() - 0.5) * 0.004; // ±0.2%
var prev = c.price;
c.price = Math.max(0.000001, c.price * (1 + delta));
c.change = +(c.change + (Math.random() - 0.5) * 0.18).toFixed(2);
c.dir = c.price >= prev ? 1 : -1;
}
renderTable();
// flash the price cell of changed rows
COINS.forEach(function (c) {
if (!c.dir) return;
var row = tbody && tbody.querySelector('tr[data-sym="' + c.sym + '"]');
if (!row) return;
var cell = row.querySelector(".price-cell");
if (cell) {
cell.classList.remove("flash-up", "flash-down", "up", "down");
void cell.offsetWidth;
cell.classList.add(c.dir > 0 ? "flash-up" : "flash-down", c.dir > 0 ? "up" : "down");
}
c.dir = 0;
});
// refresh ticker prices in place (no DOM rebuild to keep marquee smooth)
Array.prototype.forEach.call(document.querySelectorAll("#tickerTrack .ticker-item"), function (el, i) {
var c = COINS[i % COINS.length];
var up = c.change >= 0;
var px = el.querySelector(".px"), chg = el.querySelector(".chg");
if (px) px.textContent = fmtUSD(c.price);
if (chg) { chg.textContent = fmtPct(c.change); chg.className = "chg " + (up ? "pos" : "neg"); }
});
}
var jitterTimer = setInterval(jitter, 2000);
// pause jitter when tab hidden
document.addEventListener("visibilitychange", function () {
if (document.hidden) { clearInterval(jitterTimer); }
else { jitterTimer = setInterval(jitter, 2000); }
});
/* ---------- Count-up stats (animate on view) ---------- */
function countUp(el) {
var target = parseFloat(el.getAttribute("data-count")) || 0;
var dp = parseInt(el.getAttribute("data-decimals") || "0", 10);
var prefix = el.getAttribute("data-prefix") || "";
var suffix = el.getAttribute("data-suffix") || "";
var start = performance.now(), dur = 1400;
function frame(now) {
var t = Math.min(1, (now - start) / dur);
var eased = 1 - Math.pow(1 - t, 3);
var val = target * eased;
el.textContent = prefix + val.toLocaleString("en-US", {
minimumFractionDigits: dp, maximumFractionDigits: dp
}) + suffix;
if (t < 1) requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
}
var nums = Array.prototype.slice.call(document.querySelectorAll(".num[data-count]"));
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) { countUp(en.target); io.unobserve(en.target); }
});
}, { threshold: 0.4 });
nums.forEach(function (el) { io.observe(el); });
} else {
nums.forEach(countUp);
}
/* ---------- Supported assets wall ---------- */
(function assets() {
var wall = document.getElementById("assetWall");
if (!wall) return;
var extra = [
["USDQ", "Quote Dollar"], ["VLTX", "Vaultex Token"], ["KORE", "Korex"],
["PIXL", "Pixelnet"], ["TIDE", "Tidal"], ["GLDR", "Glider"],
["MANT", "Mantle Bay"], ["VOLT", "Voltage"], ["CRUX", "Cruxchain"],
["NEBU", "Nebula"], ["RUNE", "Runefi"], ["ECHO", "Echoswap"]
];
var palette = ["#f0b90b", "#16c784", "#7c5cff", "#00e0c6", "#ff9f1c", "#4ea8ff", "#ff4d6d", "#ffd23f"];
var list = COINS.map(function (c) { return [c.sym, c.name, c.c]; }).concat(
extra.map(function (e, i) { return [e[0], e[1], palette[i % palette.length]]; })
);
wall.innerHTML = list.map(function (a) {
return '<li><span class="coin-dot" style="--c:' + a[2] + '">' + a[0].charAt(0) +
'</span><span class="asset-name"><b>' + a[0] + '</b><small>' + a[1] + "</small></span></li>";
}).join("");
})();
/* ---------- Phone chart (mock bars) ---------- */
(function phoneChart() {
var chart = document.getElementById("phoneChart");
if (!chart) return;
var bars = 16, html = "";
var trend = 0;
for (var i = 0; i < bars; i++) {
trend += (Math.random() - 0.45);
var up = trend >= 0;
var hpx = 20 + Math.random() * 70;
html += '<span class="bar' + (up ? "" : " down") + '" style="height:' + hpx.toFixed(0) + '%"></span>';
}
chart.innerHTML = html;
})();
/* ---------- Signup form ---------- */
var form = document.getElementById("signupForm");
if (form) {
var input = document.getElementById("emailInput");
var hint = document.getElementById("formHint");
form.addEventListener("submit", function (e) {
e.preventDefault();
var val = (input.value || "").trim();
var ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val);
if (!ok) {
input.setAttribute("aria-invalid", "true");
if (hint) hint.textContent = "Please enter a valid email address.";
input.focus();
return;
}
input.removeAttribute("aria-invalid");
if (hint) hint.textContent = "Demo only — no account was created and no email was sent.";
input.value = "";
toast("Welcome to the demo, " + val.split("@")[0] + "! (Simulated — no real account.)");
});
}
/* ---------- Generic data-toast buttons ---------- */
Array.prototype.forEach.call(document.querySelectorAll("[data-toast]"), function (el) {
el.addEventListener("click", function (e) {
if (el.tagName === "A") e.preventDefault();
toast(el.getAttribute("data-toast"));
});
});
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-visible");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () { toastEl.classList.remove("is-visible"); }, 3200);
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vaultex — Buy, Trade & Earn Crypto</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- ===== Header ===== -->
<header class="site-header">
<div class="container header-inner">
<a class="logo" href="#" aria-label="Vaultex home">
<span class="logo-mark" aria-hidden="true">V</span>
<span class="logo-word">Vaultex</span>
</a>
<nav class="main-nav" aria-label="Primary">
<a href="#markets">Markets</a>
<a href="#features">Trade</a>
<a href="#features">Earn</a>
<a href="#fees">Fees</a>
<a href="#security">Security</a>
</nav>
<div class="header-actions">
<button class="btn btn-ghost" type="button" data-toast="Sign-in is disabled in this demo">Log in</button>
<button class="btn btn-gold" type="button" data-toast="Sign-up is simulated — no account is created">Sign up</button>
</div>
</div>
</header>
<!-- ===== Ticker tape ===== -->
<div class="ticker" aria-label="Live market ticker (simulated)">
<div class="ticker-track" id="tickerTrack"></div>
</div>
<main id="main">
<!-- ===== Hero ===== -->
<section class="hero" aria-labelledby="heroTitle">
<div class="container hero-grid">
<div class="hero-copy">
<p class="hero-eyebrow">
<span class="live-dot" aria-hidden="true"></span>
Trusted by 21M+ traders worldwide
</p>
<h1 id="heroTitle">
Trade crypto with
<span class="gold-text">institutional-grade</span>
confidence
</h1>
<p class="hero-sub">
Buy, sell and earn 350+ digital assets on Vaultex — deep liquidity,
0.02% maker fees and audited 1:1 proof of reserves. Your funds, fully backed.
</p>
<form class="signup-form" id="signupForm" novalidate>
<label class="sr-only" for="emailInput">Email address</label>
<input
id="emailInput"
class="email-input"
type="email"
inputmode="email"
autocomplete="email"
placeholder="you@example.com"
required
/>
<button class="btn btn-gold btn-lg" type="submit">Create account</button>
</form>
<p class="form-hint" id="formHint">Get up to <strong>100 USDQ</strong> in welcome rewards. Demo only — nothing is sent.</p>
<dl class="hero-stats" id="heroStats">
<div class="stat">
<dt>24h trading volume</dt>
<dd><span class="num" data-count="38.4" data-decimals="1" data-prefix="$" data-suffix="B">$0.0B</span></dd>
</div>
<div class="stat">
<dt>Registered users</dt>
<dd><span class="num" data-count="21.2" data-decimals="1" data-suffix="M">0.0M</span></dd>
</div>
<div class="stat">
<dt>Listed assets</dt>
<dd><span class="num" data-count="352" data-suffix="+">0+</span></dd>
</div>
<div class="stat">
<dt>Uptime (12 mo)</dt>
<dd><span class="num" data-count="99.99" data-decimals="2" data-suffix="%">0.00%</span></dd>
</div>
</dl>
</div>
<!-- Markets widget -->
<div class="markets-card" id="markets" aria-labelledby="marketsTitle">
<div class="markets-head">
<h2 id="marketsTitle">
Markets
<span class="live-pill"><span class="live-dot" aria-hidden="true"></span>Live</span>
</h2>
<div class="tabs" role="tablist" aria-label="Filter markets">
<button class="tab is-active" role="tab" aria-selected="true" data-filter="all" type="button">All</button>
<button class="tab" role="tab" aria-selected="false" data-filter="gainers" type="button">Gainers</button>
<button class="tab" role="tab" aria-selected="false" data-filter="losers" type="button">Losers</button>
</div>
</div>
<div class="table-wrap">
<table class="markets-table" aria-describedby="marketsNote">
<thead>
<tr>
<th scope="col" aria-sort="none">
<button class="sort-btn" type="button" data-sort="sym">Pair <span class="sort-arrow" aria-hidden="true"></span></button>
</th>
<th scope="col" class="num-col" aria-sort="none">
<button class="sort-btn" type="button" data-sort="price">Last price <span class="sort-arrow" aria-hidden="true"></span></button>
</th>
<th scope="col" class="num-col" aria-sort="none">
<button class="sort-btn" type="button" data-sort="change">24h <span class="sort-arrow" aria-hidden="true"></span></button>
</th>
<th scope="col" class="num-col hide-sm" aria-sort="none">
<button class="sort-btn" type="button" data-sort="vol">Volume <span class="sort-arrow" aria-hidden="true"></span></button>
</th>
<th scope="col" class="spark-col hide-sm">7d</th>
<th scope="col" class="action-col"><span class="sr-only">Action</span></th>
</tr>
</thead>
<tbody id="marketsBody"><!-- rows injected by script.js --></tbody>
</table>
</div>
<p class="markets-note" id="marketsNote">Simulated prices · fictional assets · updates every ~2s</p>
</div>
</div>
</section>
<!-- ===== Feature trio ===== -->
<section class="features section" id="features" aria-labelledby="featuresTitle">
<div class="container">
<h2 class="section-title" id="featuresTitle">One account. Every market.</h2>
<p class="section-sub">Spot, derivatives and yield — unified margin, one orderbook-grade engine.</p>
<div class="feature-grid">
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
<path d="M4 17l5-6 4 4 7-9" /><path d="M16 6h4v4" />
</svg>
</div>
<h3>Spot</h3>
<p>Trade 350+ pairs with maker fees from <span class="mono">0.02%</span>. Limit, market, stop and OCO orders with sub-10ms matching.</p>
<button class="card-link" type="button" data-toast="Spot trading is a demo — markets are simulated">Trade spot →</button>
</article>
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
<path d="M12 3v18" /><path d="M7 8l5-5 5 5" /><path d="M5 21h14" />
</svg>
</div>
<h3>Futures</h3>
<p>USDQ-margined perpetuals up to <span class="mono">25×</span>. Isolated & cross margin, partial liquidation engine, real-time risk.</p>
<span class="risk-tag" role="note">⚠ High risk — leverage can amplify losses</span>
<button class="card-link" type="button" data-toast="Futures require risk acknowledgement — simulated">Trade futures →</button>
</article>
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
<circle cx="12" cy="12" r="8" /><path d="M12 8v4l3 2" />
</svg>
</div>
<h3>Earn</h3>
<p>Flexible savings up to <span class="mono pos">8.2% APY</span> on USDQ and locked staking on NOVA, LMN and 40+ assets.</p>
<button class="card-link" type="button" data-toast="Earn products are illustrative — APYs are mock data">Start earning →</button>
</article>
</div>
</div>
</section>
<!-- ===== Trust / security band ===== -->
<section class="trust section" id="security" aria-labelledby="trustTitle">
<div class="container">
<div class="trust-band">
<div class="trust-headline">
<h2 id="trustTitle">Security first. Always.</h2>
<p>
<span class="mono gold-text big-num num" data-count="1.2" data-decimals="1" data-prefix="$" data-suffix="B">$0.0B</span>
insurance fund protecting user assets
</p>
</div>
<ul class="trust-badges" role="list">
<li>
<span class="badge-icon" aria-hidden="true">✓</span>
<div><strong>Proof of reserves</strong><span>Audited 1:1 monthly, on-chain attested</span></div>
</li>
<li>
<span class="badge-icon" aria-hidden="true">❄</span>
<div><strong>95% cold storage</strong><span>Multi-sig, geo-distributed vaults</span></div>
</li>
<li>
<span class="badge-icon" aria-hidden="true">🛡</span>
<div><strong>ISO/IEC 27001</strong><span>Certified security management</span></div>
</li>
<li>
<span class="badge-icon" aria-hidden="true">⚖</span>
<div><strong>Licensed & regulated</strong><span>Lumen Financial Authority · VASP-0042 (fictional)</span></div>
</li>
</ul>
</div>
</div>
</section>
<!-- ===== Fees comparison ===== -->
<section class="fees section" id="fees" aria-labelledby="feesTitle">
<div class="container">
<h2 class="section-title" id="feesTitle">Lowest fees in the game</h2>
<p class="section-sub">Keep more of every trade. No hidden spreads, no surprise withdrawal markups.</p>
<div class="table-wrap">
<table class="fees-table">
<thead>
<tr>
<th scope="col"><span class="sr-only">Fee type</span></th>
<th scope="col" class="fees-us">Vaultex</th>
<th scope="col">Exchange A</th>
<th scope="col">Exchange B</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Spot maker</th>
<td class="fees-us mono">0.02%</td>
<td class="mono">0.10%</td>
<td class="mono">0.075%</td>
</tr>
<tr>
<th scope="row">Spot taker</th>
<td class="fees-us mono">0.05%</td>
<td class="mono">0.10%</td>
<td class="mono">0.085%</td>
</tr>
<tr>
<th scope="row">USDQ withdrawal</th>
<td class="fees-us mono">Free</td>
<td class="mono">$1.00</td>
<td class="mono">$0.80</td>
</tr>
<tr>
<th scope="row">Fiat deposit</th>
<td class="fees-us mono">Free (bank)</td>
<td class="mono">0.5%</td>
<td class="mono">1.0%</td>
</tr>
</tbody>
</table>
</div>
<p class="fees-note">Comparison uses illustrative tier-0 rates against fictional competitors. Mock data.</p>
</div>
</section>
<!-- ===== Supported assets wall ===== -->
<section class="assets section" aria-labelledby="assetsTitle">
<div class="container">
<h2 class="section-title" id="assetsTitle">350+ assets supported</h2>
<p class="section-sub">From majors to new listings — all fictional, all tradable in this demo.</p>
<ul class="asset-wall" id="assetWall" role="list"><!-- injected by script.js --></ul>
</div>
</section>
<!-- ===== App download CTA ===== -->
<section class="app-cta section" aria-labelledby="appTitle">
<div class="container app-grid">
<div class="app-copy">
<h2 id="appTitle">Markets in your pocket</h2>
<p>
Price alerts, one-tap recurring buys and biometric withdrawal locks.
Rated <span class="mono gold-text">4.8★</span> by 980k traders.
</p>
<div class="store-buttons">
<button class="btn store-btn" type="button" data-toast="App Store link is simulated">
<span class="store-icon" aria-hidden="true"></span>
<span class="store-text"><small>Download on the</small>App Store</span>
</button>
<button class="btn store-btn" type="button" data-toast="Google Play link is simulated">
<span class="store-icon play" aria-hidden="true">▶</span>
<span class="store-text"><small>Get it on</small>Google Play</span>
</button>
</div>
<p class="qr-hint"><span class="qr-box" aria-hidden="true"></span> Scan to download (demo QR)</p>
</div>
<div class="phone-wrap" aria-hidden="true">
<div class="phone">
<div class="phone-notch"></div>
<div class="phone-screen">
<div class="phone-row phone-balance">
<span class="phone-label">Total balance</span>
<span class="mono phone-amount" id="phoneBalance">$24,816.07</span>
<span class="mono pos phone-pnl">+$512.44 (2.1%) today</span>
</div>
<div class="phone-chart" id="phoneChart"></div>
<div class="phone-row phone-asset">
<span class="coin-dot" style="--c:#f0b90b">N</span>
<span class="phone-asset-name">NOVA<small>Novabit</small></span>
<span class="mono phone-asset-val">0.2841<small class="pos">+2.3%</small></span>
</div>
<div class="phone-row phone-asset">
<span class="coin-dot" style="--c:#16c784">L</span>
<span class="phone-asset-name">LMN<small>Lumen</small></span>
<span class="mono phone-asset-val">142.50<small class="neg">-1.1%</small></span>
</div>
<div class="phone-actions">
<span class="phone-btn">Buy</span>
<span class="phone-btn alt">Sell</span>
</div>
</div>
</div>
<div class="phone-glow"></div>
</div>
</div>
</section>
</main>
<!-- ===== Footer ===== -->
<footer class="site-footer">
<div class="container footer-grid">
<div class="footer-brand">
<a class="logo" href="#" aria-label="Vaultex home">
<span class="logo-mark" aria-hidden="true">V</span>
<span class="logo-word">Vaultex</span>
</a>
<p>The exchange built for the next 100M traders. Fictional product — UI demo only.</p>
<p class="mono footer-addr" title="Fictional cold-wallet attestation address">PoR: 0x7a3f…c41d</p>
</div>
<nav aria-label="Products">
<h3>Products</h3>
<a href="#features">Spot trading</a>
<a href="#features">Futures</a>
<a href="#features">Earn & staking</a>
<a href="#markets">Markets</a>
</nav>
<nav aria-label="Support">
<h3>Support</h3>
<a href="#fees">Fee schedule</a>
<a href="#security">Proof of reserves</a>
<a href="#main" data-toast="Help center is a demo link">Help center</a>
<a href="#main" data-toast="API docs are a demo link">API docs</a>
</nav>
<nav aria-label="Company">
<h3>Company</h3>
<a href="#main" data-toast="Demo link">About</a>
<a href="#main" data-toast="Demo link">Careers</a>
<a href="#main" data-toast="Demo link">Press kit</a>
<a href="#main" data-toast="Demo link">Bug bounty</a>
</nav>
</div>
<div class="container footer-legal">
<p>© 2026 Vaultex Labs (fictional). Digital assets are volatile and you can lose your entire investment. This page is a static UI simulation — no real trading, custody or data.</p>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Crypto Exchange (CEX) Landing
A near-black, financial-grade marketing page for Vaultex, a fictional centralized crypto exchange. The hero leads with a clear value proposition, an email-capture sign-up form with inline validation, and four animated count-up stats (24h volume, registered users, listed assets, uptime). Gold accents and monospace numerals give it a professional, market-terminal feel while keeping WCAG AA contrast on the dark surface.
The right-hand markets widget is the centerpiece. A seamless ticker tape loops fictional tokens (NOVA, LMN, ZEPH, ORBT…) with green/red 24h moves, while a sortable top-pairs table renders coin dots, monospace prices, change pills, volume and inline SVG sparklines. Click any column header to sort, filter by gainers or losers, and watch the simulated price jitter flash cells up or down every couple of seconds. A “Trade” action and the sign-up flow surface clear simulated-only confirmation toasts so nothing reads as a real order.
The rest of the page builds trust and conversion: a Spot / Futures / Earn feature trio (with a risk
note on leverage), a security band with an insurance-fund figure and proof-of-reserves badges, a
fees comparison table against fictional competitors, a supported-assets logo wall, and an app
download CTA with an animated bar-chart phone mockup. Everything is responsive down to ~360px, the
ticker and jitter pause when the tab is hidden, and all interactions are pure vanilla JS with a small
toast() helper — no frameworks, no libraries.
UI-only simulation — no real wallet, RPC, or on-chain calls. Mock data, fictional tokens.