Files
zeekayandHanzo Dev 4d4fa23382 Lux branding on every screen, in the Lux faces
The demo tenant conceit is gone: mockups and the six animated
screens brand as Lux with the triangle mark. The site drops Zen for
the brand faces — Lux Sans for text, Lux Display for the hero, both
vendored until @luxfi/font is on the registry. Screens record on
pure black, and the showcase leads with a full-width frame.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-31 13:21:25 -07:00

95 lines
6.9 KiB
HTML

<!doctype html>
<html><head><meta charset="utf-8"><link rel="stylesheet" href="lib.css">
<style>
.cust-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 20px; flex: 1; min-height: 0; }
.ceremony { display: flex; flex-direction: column; gap: 16px; justify-content: space-evenly; }
.shares { display: flex; justify-content: space-around; padding: 18px 0 6px; }
.share { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.share .node {
width: 96px; height: 96px; border-radius: 24px;
background: var(--panel2); border: 1.5px solid var(--line2);
display: flex; align-items: center; justify-content: center;
font-size: 24px; transition: all 0.5s ease; position: relative;
}
.share .node svg { width: 38px; height: 38px; stroke: var(--ink3); fill: none; stroke-width: 1.6; transition: stroke 0.5s ease; }
.share.lit .node { border-color: var(--gold); box-shadow: 0 0 26px rgba(212, 175, 55, 0.35); }
.share.lit .node svg { stroke: var(--gold); }
.share .nm { font-size: 12px; font-weight: 600; color: var(--ink2); }
.share .loc { font-size: 10.5px; color: var(--ink3); }
.sigbar { height: 8px; border-radius: 99px; background: var(--panel2); border: 1px solid var(--line); overflow: hidden; }
.sigbar > div { height: 100%; width: 0; border-radius: 99px; background: linear-gradient(90deg, #8a6d1f, #e8cd6a); transition: width 1.2s cubic-bezier(0.4, 0, 0.2, 1); }
.sigrow { display: flex; justify-content: space-between; align-items: center; font-size: 12.5px; color: var(--ink2); }
.req { display: flex; justify-content: space-between; align-items: center; background: var(--panel2); border: 1px solid var(--line2); border-radius: 12px; padding: 14px 16px; }
.req .what { font-weight: 650; font-size: 13.5px; }
.req .sub { color: var(--ink3); font-size: 11.5px; margin-top: 3px; }
.row { grid-template-columns: 1.7fr 1fr 1fr 0.9fr; }
.thead { grid-template-columns: 1.7fr 1fr 1fr 0.9fr; }
.keyfact { display: flex; gap: 8px; align-items: baseline; font-size: 12px; color: var(--ink3); padding: 2px 4px; }
.keyfact b { color: var(--ink2); font-weight: 650; }
</style></head>
<body><div class="app">
<aside class="side">
<div class="brand"><div class="brand-mark">▼</div><div class="brand-name">Lux</div></div>
<div class="nav-item"><svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>Dashboard</div>
<div class="nav-item active"><svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>Custody</div>
<div class="nav-item"><svg viewBox="0 0 24 24"><path d="M21 8v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8m18 0V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2m18 0H3"/></svg>Wallets</div>
<div class="nav-item"><svg viewBox="0 0 24 24"><path d="M3 3v18h18"/><path d="M7 14l4-4 4 4 5-6"/></svg>Audit</div>
<div class="foot"><span class="env-dot"></span>MPC · 2-of-3 threshold</div>
</aside>
<main class="main">
<div class="topbar fx"><h1>MPC custody</h1><div class="who"><span class="pill"><span class="env-dot"></span>Signer set healthy</span><div class="avatar">LX</div></div></div>
<div class="cust-grid">
<div class="card ceremony fx">
<div class="label">Signing ceremony</div>
<div class="req">
<div><div class="what" id="reqw">Withdraw 12.5 BTC → cold vault</div><div class="sub">Policy: 2-of-3 shares · velocity limit OK · destination allowlisted</div></div>
<span class="tag wait" id="reqtag">Awaiting shares</span>
</div>
<div class="shares">
<div class="share" id="sh1"><div class="node"><svg viewBox="0 0 24 24"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div><span class="nm">Share A</span><span class="loc">HSM · NY4</span></div>
<div class="share" id="sh2"><div class="node"><svg viewBox="0 0 24 24"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div><span class="nm">Share B</span><span class="loc">KMS · Zurich</span></div>
<div class="share" id="sh3"><div class="node"><svg viewBox="0 0 24 24"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div><span class="nm">Share C</span><span class="loc">Mobile · client</span></div>
</div>
<div class="sigrow"><span>Threshold signature — CGGMP21</span><span class="mono" id="sigpct">0%</span></div>
<div class="sigbar"><div id="sig"></div></div>
<div class="keyfact"><b>The full private key never exists.</b><span>Shares compute the signature together; no machine ever holds the key.</span></div>
</div>
<div class="table fx" style="flex:none;">
<div class="thead"><span>Event</span><span>Asset</span><span>Policy</span><span>Result</span></div>
<div id="audit"></div>
</div>
</div>
</main>
</div>
<script>
const $ = (id) => document.getElementById(id);
const audit = [
['Withdraw → cold vault', '12.5 BTC', '2-of-3', 'ok', 'Signed'],
['Bridge transfer', '250K USDC', '2-of-3', 'ok', 'Signed'],
['Key rotation', 'Vault #4', 'quorum', 'ok', 'Rotated'],
['Withdraw attempt', '80 ETH', 'velocity', 'bad', 'Blocked'],
['Staking delegation', '10K LUX', '2-of-3', 'ok', 'Signed'],
];
function addAudit([ev, asset, pol, cls, res], flash) {
const d = document.createElement('div');
d.className = 'row' + (flash ? ' flash' : '');
d.style.gridTemplateColumns = '1.7fr 1fr 1fr 0.9fr';
d.innerHTML = `<span>${ev}</span><span class="mono" style="color:var(--ink2)">${asset}</span><span style="color:var(--ink3);font-size:12px;">${pol}</span><span class="tag ${cls}">${res}</span>`;
$('audit').prepend(d);
while ($('audit').children.length > 6) $('audit').lastChild.remove();
}
function cycle() {
document.querySelectorAll('.fx').forEach((el, i) => { el.classList.remove('in'); setTimeout(() => el.classList.add('in'), 80 + i * 110); });
['sh1','sh2','sh3'].forEach(id => $(id).classList.remove('lit'));
$('sig').style.width = '0%'; $('sigpct').textContent = '0%';
$('reqtag').className = 'tag wait'; $('reqtag').textContent = 'Awaiting shares';
$('audit').innerHTML = '';
audit.slice(1).reverse().forEach(r => addAudit(r, false));
setTimeout(() => $('sh1').classList.add('lit'), 1800);
setTimeout(() => { $('sh3').classList.add('lit'); $('sig').style.width = '55%'; $('sigpct').textContent = '55%'; }, 2900);
setTimeout(() => { $('sig').style.width = '100%'; $('sigpct').textContent = '100%'; }, 4100);
setTimeout(() => { $('reqtag').className = 'tag ok'; $('reqtag').textContent = 'Signed ✓'; addAudit(audit[0], true); }, 5400);
}
cycle(); setInterval(cycle, 8000);
</script></body></html>