Initial backup of root workspace files
Glue files not covered by subproject repos: top-level docs, logo, keysat-design-system, and crosscheck tests. Subproject folders are gitignored (each has its own Gitea remote).
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# Keysat — Dashboard UI Kit
|
||||
|
||||
The creator's admin panel. Runs on the creator's own Start9. Manages products, policies, license keys, customers, discount codes, and the audit log.
|
||||
|
||||
## Files
|
||||
|
||||
- `index.html` — entry view (Overview / dashboard home).
|
||||
- `licenses.html` — license list, with row-level actions.
|
||||
- `license-detail.html` — single license: certificate-style header, customer info, audit timeline, revoke action.
|
||||
- `new-product.html` — create-product flow (product details + policy + price).
|
||||
- `signin.html` — admin sign-in (paste admin API key).
|
||||
|
||||
## Components (inline in each page)
|
||||
|
||||
- **Sidebar** — wordmark, primary nav (Overview, Products, Licenses, Customers, Discounts, Audit, Settings), BTCPay connection status footer.
|
||||
- **Topbar** — page title, breadcrumb, primary action button, search.
|
||||
- **Stat cards** — KPI tiles (active licenses, sales 30d, sats earned).
|
||||
- **Table** — license list, customer list. 52px rows, mono key column, status badge column.
|
||||
- **Drawer / detail header** — certificate motif borrowed from the marketing hero.
|
||||
- **Empty state** — gold-bordered cream card with a single Lucide icon.
|
||||
|
||||
## Iconography
|
||||
|
||||
Lucide via CDN. Stroke 1.75px, 18px in nav, 16px inline.
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- The "Settings" tab from the user's brief was scoped down to **operator settings** (operator name, public key, BTCPay connection). Payouts removed because BTCPay handles money.
|
||||
- All data is fake.
|
||||
@@ -0,0 +1,206 @@
|
||||
/* Shared dashboard chrome — links to ../../colors_and_type.css for tokens */
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: var(--font-body);
|
||||
font-size: 14px;
|
||||
color: var(--ink-900);
|
||||
background: var(--cream-100);
|
||||
background-image:
|
||||
radial-gradient(rgba(14,31,51,0.022) 1px, transparent 1px),
|
||||
radial-gradient(rgba(138,111,61,0.020) 1px, transparent 1px);
|
||||
background-size: 3px 3px, 7px 7px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
a { color: var(--navy-800); text-decoration: none; }
|
||||
|
||||
/* ---------- Layout ---------- */
|
||||
.app { display: grid; grid-template-columns: 240px 1fr; min-height: 100vh; }
|
||||
|
||||
/* ---------- Sidebar ---------- */
|
||||
.sidebar {
|
||||
background: var(--navy-950);
|
||||
color: var(--cream-200);
|
||||
padding: 24px 14px;
|
||||
display: flex; flex-direction: column;
|
||||
border-right: 1px solid var(--navy-900);
|
||||
}
|
||||
.sidebar .brand {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
font-family: var(--font-display); font-weight: 500; font-size: 14px; letter-spacing: 0.28em; text-transform: uppercase;
|
||||
color: var(--cream-50);
|
||||
padding: 0 8px 22px;
|
||||
border-bottom: 1px solid rgba(245,241,232,0.10);
|
||||
margin-bottom: 14px;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
.sidebar .brand img { width: 26px; height: 26px; }
|
||||
.sidebar .group-label {
|
||||
font-size: 10px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
|
||||
color: var(--gold-400); padding: 16px 10px 8px;
|
||||
}
|
||||
.sidebar a.nav {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 9px 10px; border-radius: 6px;
|
||||
font-size: 13.5px; color: rgba(245,241,232,0.72);
|
||||
transition: all 120ms;
|
||||
}
|
||||
.sidebar a.nav:hover { background: rgba(245,241,232,0.06); color: var(--cream-50); }
|
||||
.sidebar a.nav.active { background: var(--navy-800); color: var(--cream-50); }
|
||||
.sidebar a.nav [data-lucide] { width: 16px; height: 16px; }
|
||||
.sidebar a.nav .count {
|
||||
margin-left: auto; font-family: var(--font-mono); font-size: 11px;
|
||||
background: rgba(245,241,232,0.10); color: var(--cream-200);
|
||||
padding: 1px 7px; border-radius: 999px;
|
||||
}
|
||||
.sidebar a.nav.active .count { background: var(--gold-500); color: var(--navy-950); }
|
||||
.sidebar .footer {
|
||||
margin-top: auto; padding: 14px 10px; border-top: 1px solid rgba(245,241,232,0.10);
|
||||
font-size: 12px; color: rgba(245,241,232,0.55); display: flex; gap: 10px; align-items: center;
|
||||
}
|
||||
.sidebar .footer .dot { width: 7px; height: 7px; border-radius: 50%; background: #2D7A5F; box-shadow: 0 0 0 3px rgba(45,122,95,0.25); }
|
||||
|
||||
/* ---------- Main ---------- */
|
||||
.main { display: flex; flex-direction: column; min-width: 0; }
|
||||
.topbar {
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
padding: 18px 32px; border-bottom: 1px solid var(--border-1);
|
||||
background: rgba(251,249,242,0.92);
|
||||
backdrop-filter: blur(8px);
|
||||
position: sticky; top: 0; z-index: 5;
|
||||
}
|
||||
.topbar .crumb { font-size: 12.5px; color: var(--ink-500); }
|
||||
.topbar h1 {
|
||||
font-family: var(--font-display); font-weight: 700; font-size: 22px;
|
||||
letter-spacing: -0.015em; margin: 2px 0 0; color: var(--navy-950);
|
||||
}
|
||||
.topbar .search {
|
||||
margin-left: auto;
|
||||
position: relative; width: 280px;
|
||||
}
|
||||
.topbar .search input {
|
||||
width: 100%; padding: 8px 12px 8px 32px;
|
||||
font-family: var(--font-body); font-size: 13px;
|
||||
border: 1px solid var(--border-1);
|
||||
border-radius: 8px; background: var(--cream-50);
|
||||
color: var(--ink-900);
|
||||
}
|
||||
.topbar .search input:focus { outline: none; border-color: var(--navy-700); box-shadow: 0 0 0 3px rgba(30,58,95,0.15); }
|
||||
.topbar .search [data-lucide] { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 14px; height: 14px; color: var(--ink-400); }
|
||||
.topbar .topbar-actions { display: flex; gap: 8px; align-items: center; }
|
||||
|
||||
.content { padding: 28px 32px 64px; max-width: 1280px; }
|
||||
|
||||
/* ---------- Buttons ---------- */
|
||||
.btn {
|
||||
display: inline-flex; align-items: center; gap: 7px;
|
||||
font-family: var(--font-body); font-weight: 600; font-size: 13px;
|
||||
padding: 8px 14px; border-radius: 7px; border: 1px solid transparent;
|
||||
cursor: pointer; transition: all 120ms; line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.btn [data-lucide] { width: 14px; height: 14px; }
|
||||
.btn.lg { font-size: 14px; padding: 11px 18px; }
|
||||
.btn.sm { font-size: 12px; padding: 6px 10px; }
|
||||
.btn.primary { background: var(--navy-800); color: var(--cream-50); border-color: var(--navy-800); }
|
||||
.btn.primary:hover { background: var(--navy-900); border-color: var(--navy-900); }
|
||||
.btn.secondary { background: var(--cream-50); color: var(--navy-900); border-color: var(--border-2); }
|
||||
.btn.secondary:hover { background: var(--cream-200); }
|
||||
.btn.ghost { background: transparent; color: var(--navy-900); }
|
||||
.btn.ghost:hover { background: rgba(14,31,51,0.06); }
|
||||
.btn.danger { color: var(--danger); border-color: rgba(178,58,58,0.3); background: transparent; }
|
||||
.btn.danger:hover { background: var(--danger-bg); }
|
||||
|
||||
/* ---------- Cards ---------- */
|
||||
.card {
|
||||
background: var(--cream-50);
|
||||
border: 1px solid var(--border-1);
|
||||
border-radius: 10px;
|
||||
box-shadow: var(--shadow-xs);
|
||||
}
|
||||
.card .card-head {
|
||||
padding: 14px 18px; border-bottom: 1px solid var(--border-1);
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
}
|
||||
.card .card-head h3 {
|
||||
font-family: var(--font-display); font-weight: 700; font-size: 15px;
|
||||
margin: 0; letter-spacing: -0.01em; color: var(--navy-950);
|
||||
}
|
||||
|
||||
/* ---------- Stats ---------- */
|
||||
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 24px; }
|
||||
.stat {
|
||||
background: var(--cream-50); border: 1px solid var(--border-1);
|
||||
border-radius: 10px; padding: 18px 18px 16px;
|
||||
position: relative; overflow: hidden;
|
||||
}
|
||||
.stat::before {
|
||||
content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
|
||||
background: var(--gold-500); opacity: 0;
|
||||
}
|
||||
.stat.featured::before { opacity: 1; }
|
||||
.stat .label {
|
||||
font-size: 11px; font-weight: 700; letter-spacing: 0.14em;
|
||||
text-transform: uppercase; color: var(--ink-500); margin-bottom: 8px;
|
||||
}
|
||||
.stat .value {
|
||||
font-family: var(--font-display); font-weight: 500; font-size: 30px;
|
||||
color: var(--navy-950); letter-spacing: -0.022em; line-height: 1;
|
||||
}
|
||||
.stat .value .unit { font-family: var(--font-body); font-size: 13px; font-weight: 600; color: var(--ink-500); margin-left: 6px; }
|
||||
.stat .delta { font-size: 12px; color: var(--success); margin-top: 8px; font-weight: 600; }
|
||||
.stat .delta.down { color: var(--danger); }
|
||||
.stat .sub { font-size: 12px; color: var(--ink-500); margin-top: 6px; }
|
||||
|
||||
/* ---------- Table ---------- */
|
||||
table.t {
|
||||
width: 100%; border-collapse: separate; border-spacing: 0;
|
||||
background: var(--cream-50); border: 1px solid var(--border-1);
|
||||
border-radius: 10px; overflow: hidden;
|
||||
}
|
||||
table.t thead th {
|
||||
text-align: left; font-size: 11px; font-weight: 700;
|
||||
letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-500);
|
||||
padding: 12px 16px; background: var(--cream-100);
|
||||
border-bottom: 1px solid var(--border-1);
|
||||
}
|
||||
table.t tbody td {
|
||||
padding: 14px 16px; border-bottom: 1px solid var(--border-1);
|
||||
font-size: 13.5px; color: var(--ink-700); vertical-align: middle;
|
||||
}
|
||||
table.t tbody tr:last-child td { border-bottom: 0; }
|
||||
table.t tbody tr:hover { background: var(--cream-100); cursor: pointer; }
|
||||
table.t .key { font-family: var(--font-mono); font-size: 12.5px; color: var(--navy-900); font-weight: 600; }
|
||||
table.t .product { font-weight: 600; color: var(--navy-950); }
|
||||
table.t .meta { color: var(--ink-500); font-size: 12px; }
|
||||
|
||||
/* ---------- Badges ---------- */
|
||||
.badge {
|
||||
display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600;
|
||||
padding: 2px 9px; border-radius: 999px; line-height: 1.5; border: 1px solid transparent;
|
||||
}
|
||||
.b-success { background: var(--success-bg); color: #205c47; border-color: rgba(45,122,95,0.25); }
|
||||
.b-warning { background: var(--warning-bg); color: #7a5814; border-color: rgba(184,134,31,0.3); }
|
||||
.b-danger { background: var(--danger-bg); color: #8a2828; border-color: rgba(178,58,58,0.25); }
|
||||
.b-info { background: var(--navy-100); color: var(--navy-800); border-color: rgba(30,58,95,0.20); }
|
||||
.b-neutral { background: var(--cream-200); color: var(--ink-700); border-color: var(--border-1); }
|
||||
.b-gold { background: transparent; color: var(--gold-700); border-color: var(--gold-500); }
|
||||
.dot { width: 6px; height: 6px; border-radius: 50%; }
|
||||
|
||||
/* ---------- Forms ---------- */
|
||||
.field { margin-bottom: 14px; }
|
||||
.field label.lbl { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-700); margin-bottom: 6px; }
|
||||
.field .hint { font-size: 12px; color: var(--ink-500); margin-top: 5px; }
|
||||
.input, .select {
|
||||
width: 100%; padding: 9px 12px; font-family: var(--font-body); font-size: 13.5px;
|
||||
border: 1px solid var(--border-2); border-radius: 7px; background: #FFFFFF;
|
||||
color: var(--ink-900); transition: all 120ms;
|
||||
}
|
||||
.input:focus, .select:focus { outline: none; border-color: var(--navy-700); box-shadow: 0 0 0 3px rgba(30,58,95,0.18); }
|
||||
.input.mono { font-family: var(--font-mono); font-size: 13px; }
|
||||
|
||||
.eyebrow {
|
||||
font-size: 10.5px; font-weight: 700; letter-spacing: 0.18em;
|
||||
text-transform: uppercase; color: var(--gold-700);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Keysat — Overview</title>
|
||||
<link rel="stylesheet" href="../../colors_and_type.css">
|
||||
<link rel="stylesheet" href="dash.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<aside class="sidebar">
|
||||
<div class="brand"><img src="../../assets/keysat-mark.svg" alt=""><span>Keysat</span></div>
|
||||
<a class="nav active" href="index.html"><i data-lucide="layout-dashboard"></i>Overview</a>
|
||||
<a class="nav" href="#"><i data-lucide="package"></i>Products<span class="count">3</span></a>
|
||||
<a class="nav" href="licenses.html"><i data-lucide="key-round"></i>Licenses<span class="count">42</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="users"></i>Customers<span class="count">38</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="tag"></i>Discount codes</a>
|
||||
<div class="group-label">System</div>
|
||||
<a class="nav" href="#"><i data-lucide="scroll-text"></i>Audit log</a>
|
||||
<a class="nav" href="#"><i data-lucide="webhook"></i>Webhooks</a>
|
||||
<a class="nav" href="#"><i data-lucide="settings-2"></i>Settings</a>
|
||||
<div class="footer"><span class="dot"></span><div><div style="color: var(--cream-50); font-weight: 600">BTCPay connected</div><div>store: aurora-software</div></div></div>
|
||||
</aside>
|
||||
|
||||
<main class="main">
|
||||
<header class="topbar">
|
||||
<div>
|
||||
<div class="crumb">Workspace · aurora-software</div>
|
||||
<h1>Overview</h1>
|
||||
</div>
|
||||
<div class="search"><i data-lucide="search"></i><input placeholder="Search licenses, customers, products"></div>
|
||||
<div class="topbar-actions">
|
||||
<button class="btn secondary"><i data-lucide="download"></i>Export</button>
|
||||
<button class="btn primary"><i data-lucide="plus"></i>New product</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="stats">
|
||||
<div class="stat featured">
|
||||
<div class="label">Active licenses</div>
|
||||
<div class="value">42</div>
|
||||
<div class="delta">+5 this month</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="label">Sales · 30 days</div>
|
||||
<div class="value">12 <span class="unit">sales</span></div>
|
||||
<div class="delta">+33% vs prev</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="label">Sats earned · 30d</div>
|
||||
<div class="value">412,500</div>
|
||||
<div class="sub">≈ $247.32</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="label">Conversion</div>
|
||||
<div class="value">8.4 <span class="unit">%</span></div>
|
||||
<div class="delta down">−1.2% vs prev</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1.6fr 1fr; gap: 18px;">
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Recent licenses</h3><a href="licenses.html" class="btn ghost sm">View all <i data-lucide="arrow-right"></i></a></div>
|
||||
<table class="t" style="border:0; border-radius: 0;">
|
||||
<thead><tr><th>Key</th><th>Product</th><th>Customer</th><th>Status</th><th>Issued</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="key">KS-9F2A-7C41-XK22-6D8E</td><td class="product">Sundial 2.0</td><td>nina@dial.studio</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">2 hours ago</td></tr>
|
||||
<tr><td class="key">KS-A14C-PT09-LM31-R7Q4</td><td class="product">Sundial Pro</td><td>m@labry.dev</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">Yesterday</td></tr>
|
||||
<tr><td class="key">KS-T2X8-6K43-QQ91-WE0M</td><td class="product">Sundial 2.0</td><td>jo@kestrel.fm</td><td><span class="badge b-warning"><span class="dot" style="background:#B8861F"></span>Trial</span></td><td class="meta">2d ago</td></tr>
|
||||
<tr><td class="key">KS-BX9D-MM21-NU45-7F3R</td><td class="product">Sundial 2.0</td><td>ari@northpath.io</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">3d ago</td></tr>
|
||||
<tr><td class="key">KS-PW45-VR82-XA61-9K0L</td><td class="product">Sundial Pro</td><td>tom@workhorse.app</td><td><span class="badge b-danger"><span class="dot" style="background:#B23A3A"></span>Revoked</span></td><td class="meta">5d ago</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 14px;">
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Top products</h3></div>
|
||||
<div style="padding: 12px 16px;">
|
||||
<div style="display: flex; align-items: center; padding: 10px 0; gap: 12px; border-bottom: 1px solid var(--border-1);">
|
||||
<div style="flex: 1;"><div style="font-weight: 600; color: var(--navy-950)">Sundial 2.0</div><div style="font-size: 12px; color: var(--ink-500)">28 active · 50,000 sats</div></div>
|
||||
<div style="font-family: var(--font-mono); font-size: 12.5px; color: var(--navy-900); font-weight: 600">1.4M sats</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; padding: 10px 0; gap: 12px; border-bottom: 1px solid var(--border-1);">
|
||||
<div style="flex: 1;"><div style="font-weight: 600; color: var(--navy-950)">Sundial Pro</div><div style="font-size: 12px; color: var(--ink-500)">11 active · 200,000 sats</div></div>
|
||||
<div style="font-family: var(--font-mono); font-size: 12.5px; color: var(--navy-900); font-weight: 600">2.2M sats</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; padding: 10px 0; gap: 12px;">
|
||||
<div style="flex: 1;"><div style="font-weight: 600; color: var(--navy-950)">Aurora Plugin</div><div style="font-size: 12px; color: var(--ink-500)">3 active · 75,000 sats</div></div>
|
||||
<div style="font-family: var(--font-mono); font-size: 12.5px; color: var(--navy-900); font-weight: 600">225k sats</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="background: var(--cream-100); border-style: dashed;">
|
||||
<div style="padding: 18px;">
|
||||
<div class="eyebrow" style="margin-bottom: 6px;">Tip</div>
|
||||
<div style="font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--navy-950); margin-bottom: 4px; letter-spacing: -0.01em;">Embed your public key</div>
|
||||
<p style="font-size: 13px; color: var(--ink-700); margin: 0 0 12px; line-height: 1.5;">Paste this into your app's source. Verifies signatures offline.</p>
|
||||
<div style="background: var(--navy-950); color: var(--cream-50); padding: 10px 12px; border-radius: 7px; font-family: var(--font-mono); font-size: 12px; display: flex; gap: 10px; align-items: center; justify-content: space-between;">
|
||||
<span>mz7q8r4t1v…h3k2pXq9wL</span>
|
||||
<button class="btn sm" style="background: rgba(245,241,232,0.10); color: var(--cream-50); border: 0;">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script>lucide.createIcons();</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,106 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Keysat — License KS-9F2A-7C41-XK22-6D8E</title>
|
||||
<link rel="stylesheet" href="../../colors_and_type.css">
|
||||
<link rel="stylesheet" href="dash.css">
|
||||
<style>
|
||||
.detail-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 18px; align-items: start; }
|
||||
.cert-head { background: var(--cream-50); border: 1px solid var(--border-1); border-radius: 12px; box-shadow: 0 0 0 1px var(--gold-500) inset, var(--shadow-sm); padding: 28px; position: relative; }
|
||||
.cert-head::before, .cert-head::after { content: ''; position: absolute; left: 14px; right: 14px; height: 1px; background: var(--gold-500); opacity: 0.4; }
|
||||
.cert-head::before { top: 14px; } .cert-head::after { bottom: 14px; }
|
||||
.cert-stamp { font-size: 10px; font-weight: 700; letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold-700); margin-bottom: 14px; }
|
||||
.cert-key { font-family: var(--font-mono); font-size: 22px; font-weight: 600; color: var(--navy-950); letter-spacing: 0.02em; margin-bottom: 8px; }
|
||||
.cert-product { font-family: var(--font-display); font-weight: 700; font-size: 18px; color: var(--ink-700); margin-bottom: 18px; }
|
||||
.cert-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; padding-top: 16px; border-top: 1px dashed rgba(14,31,51,0.18); }
|
||||
.cert-grid .field { font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-500); margin-bottom: 4px; }
|
||||
.cert-grid .value { font-family: var(--font-mono); font-size: 13px; color: var(--navy-900); font-weight: 500; }
|
||||
.timeline { padding: 4px 16px; }
|
||||
.timeline .item { display: grid; grid-template-columns: 18px 1fr; gap: 10px; padding: 12px 0; border-bottom: 1px solid var(--border-1); }
|
||||
.timeline .item:last-child { border-bottom: 0; }
|
||||
.timeline .marker { width: 8px; height: 8px; border-radius: 50%; background: var(--navy-800); margin-top: 6px; }
|
||||
.timeline .marker.gold { background: var(--gold-500); }
|
||||
.timeline .marker.danger { background: var(--danger); }
|
||||
.timeline .head { font-size: 13px; font-weight: 600; color: var(--navy-950); }
|
||||
.timeline .meta { font-size: 12px; color: var(--ink-500); margin-top: 2px; font-family: var(--font-mono); }
|
||||
.timeline .body { font-size: 12.5px; color: var(--ink-700); margin-top: 4px; }
|
||||
.info-row { display: flex; justify-content: space-between; padding: 10px 16px; border-bottom: 1px solid var(--border-1); font-size: 13px; }
|
||||
.info-row:last-child { border-bottom: 0; }
|
||||
.info-row .k { color: var(--ink-500); }
|
||||
.info-row .v { color: var(--navy-900); font-weight: 500; }
|
||||
.actions-row { display: flex; gap: 8px; margin-top: 16px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<aside class="sidebar">
|
||||
<div class="brand"><img src="../../assets/keysat-mark.svg" alt=""><span>Keysat</span></div>
|
||||
<a class="nav" href="index.html"><i data-lucide="layout-dashboard"></i>Overview</a>
|
||||
<a class="nav" href="#"><i data-lucide="package"></i>Products<span class="count">3</span></a>
|
||||
<a class="nav active" href="licenses.html"><i data-lucide="key-round"></i>Licenses<span class="count">42</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="users"></i>Customers<span class="count">38</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="tag"></i>Discount codes</a>
|
||||
<div class="group-label">System</div>
|
||||
<a class="nav" href="#"><i data-lucide="scroll-text"></i>Audit log</a>
|
||||
<a class="nav" href="#"><i data-lucide="webhook"></i>Webhooks</a>
|
||||
<a class="nav" href="#"><i data-lucide="settings-2"></i>Settings</a>
|
||||
<div class="footer"><span class="dot"></span><div><div style="color: var(--cream-50); font-weight: 600">BTCPay connected</div><div>store: aurora-software</div></div></div>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<header class="topbar">
|
||||
<div><div class="crumb"><a href="licenses.html">Licenses</a> · KS-9F2A-7C41-XK22-6D8E</div><h1>License detail</h1></div>
|
||||
<div class="topbar-actions">
|
||||
<button class="btn secondary"><i data-lucide="copy"></i>Copy key</button>
|
||||
<button class="btn secondary"><i data-lucide="mail"></i>Resend email</button>
|
||||
<button class="btn danger"><i data-lucide="x-circle"></i>Revoke</button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="cert-head">
|
||||
<div class="cert-stamp">— Certificate of License · Active —</div>
|
||||
<div class="cert-key">KS-9F2A-7C41-XK22-6D8E</div>
|
||||
<div class="cert-product">Sundial 2.0 · default policy</div>
|
||||
<div class="cert-grid">
|
||||
<div><div class="field">Issued</div><div class="value">2026-04-22</div></div>
|
||||
<div><div class="field">Expires</div><div class="value">2027-04-22</div></div>
|
||||
<div><div class="field">Seats</div><div class="value">1 of 1</div></div>
|
||||
<div><div class="field">Trial</div><div class="value">No</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-grid" style="margin-top: 18px;">
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Audit timeline</h3></div>
|
||||
<div class="timeline">
|
||||
<div class="item"><div class="marker gold"></div><div><div class="head">License issued</div><div class="meta">2026-04-22 · 14:32 · BTCPay invoice INV-9F2A</div><div class="body">Signed with issuer key mz7q8r4t1v…h3k2pXq9wL.</div></div></div>
|
||||
<div class="item"><div class="marker"></div><div><div class="head">Payment confirmed</div><div class="meta">2026-04-22 · 14:31 · 50,000 sats · Lightning</div><div class="body">Settled in 1 confirmation. Funds routed to wallet "aurora".</div></div></div>
|
||||
<div class="item"><div class="marker"></div><div><div class="head">Invoice created</div><div class="meta">2026-04-22 · 14:29</div><div class="body">Buyer landed on purchase URL from /pricing.</div></div></div>
|
||||
<div class="item"><div class="marker"></div><div><div class="head">First verification</div><div class="meta">2026-04-22 · 15:11 · 10.0.4.118</div><div class="body">Sundial v2.0.3 verified key offline at startup.</div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 14px;">
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Customer</h3></div>
|
||||
<div class="info-row"><span class="k">Email</span><span class="v">nina@dial.studio</span></div>
|
||||
<div class="info-row"><span class="k">npub</span><span class="v" style="font-family: var(--font-mono); font-size: 12px">npub1aw…q4t8</span></div>
|
||||
<div class="info-row"><span class="k">First seen</span><span class="v">2 hours ago</span></div>
|
||||
<div class="info-row"><span class="k">Other licenses</span><span class="v">1 (Aurora Plugin)</span></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Policy</h3></div>
|
||||
<div class="info-row"><span class="k">Slug</span><span class="v" style="font-family: var(--font-mono)">default</span></div>
|
||||
<div class="info-row"><span class="k">Duration</span><span class="v">1 year</span></div>
|
||||
<div class="info-row"><span class="k">Seats</span><span class="v">1</span></div>
|
||||
<div class="info-row"><span class="k">Entitlements</span><span class="v">core, sync, export</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script>lucide.createIcons();</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Keysat — Licenses</title>
|
||||
<link rel="stylesheet" href="../../colors_and_type.css">
|
||||
<link rel="stylesheet" href="dash.css">
|
||||
<style>
|
||||
.toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
|
||||
.chip { font-size: 12.5px; padding: 6px 12px; border-radius: 999px; background: var(--cream-50); border: 1px solid var(--border-1); color: var(--ink-700); cursor: pointer; }
|
||||
.chip.active { background: var(--navy-800); color: var(--cream-50); border-color: var(--navy-800); }
|
||||
.chip .count { opacity: 0.6; margin-left: 4px; }
|
||||
.filter-spacer { flex: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<aside class="sidebar">
|
||||
<div class="brand"><img src="../../assets/keysat-mark.svg" alt=""><span>Keysat</span></div>
|
||||
<a class="nav" href="index.html"><i data-lucide="layout-dashboard"></i>Overview</a>
|
||||
<a class="nav" href="#"><i data-lucide="package"></i>Products<span class="count">3</span></a>
|
||||
<a class="nav active" href="licenses.html"><i data-lucide="key-round"></i>Licenses<span class="count">42</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="users"></i>Customers<span class="count">38</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="tag"></i>Discount codes</a>
|
||||
<div class="group-label">System</div>
|
||||
<a class="nav" href="#"><i data-lucide="scroll-text"></i>Audit log</a>
|
||||
<a class="nav" href="#"><i data-lucide="webhook"></i>Webhooks</a>
|
||||
<a class="nav" href="#"><i data-lucide="settings-2"></i>Settings</a>
|
||||
<div class="footer"><span class="dot"></span><div><div style="color: var(--cream-50); font-weight: 600">BTCPay connected</div><div>store: aurora-software</div></div></div>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<header class="topbar">
|
||||
<div><div class="crumb">Workspace · aurora-software</div><h1>Licenses</h1></div>
|
||||
<div class="search"><i data-lucide="search"></i><input placeholder="Search by key, email, product…"></div>
|
||||
<div class="topbar-actions">
|
||||
<button class="btn secondary"><i data-lucide="download"></i>Export</button>
|
||||
<button class="btn primary"><i data-lucide="plus"></i>Issue license</button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="toolbar">
|
||||
<span class="chip active">All<span class="count">42</span></span>
|
||||
<span class="chip">Active<span class="count">35</span></span>
|
||||
<span class="chip">Trial<span class="count">4</span></span>
|
||||
<span class="chip">Expired<span class="count">2</span></span>
|
||||
<span class="chip">Revoked<span class="count">1</span></span>
|
||||
<div class="filter-spacer"></div>
|
||||
<button class="btn ghost sm"><i data-lucide="filter"></i>Filter</button>
|
||||
<button class="btn ghost sm"><i data-lucide="arrow-up-down"></i>Sort: newest</button>
|
||||
</div>
|
||||
<table class="t">
|
||||
<thead><tr><th>License key</th><th>Product</th><th>Customer</th><th>Status</th><th>Expires</th><th>Issued</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="key">KS-9F2A-7C41-XK22-6D8E</td><td class="product">Sundial 2.0</td><td>nina@dial.studio</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">Apr 2027</td><td class="meta">2 hours ago</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
<tr><td class="key">KS-A14C-PT09-LM31-R7Q4</td><td class="product">Sundial Pro</td><td>m@labry.dev</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta"><span class="badge b-gold">Lifetime</span></td><td class="meta">Yesterday</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
<tr><td class="key">KS-T2X8-6K43-QQ91-WE0M</td><td class="product">Sundial 2.0</td><td>jo@kestrel.fm</td><td><span class="badge b-warning"><span class="dot" style="background:#B8861F"></span>Trial</span></td><td class="meta">in 12 days</td><td class="meta">2d ago</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
<tr><td class="key">KS-BX9D-MM21-NU45-7F3R</td><td class="product">Sundial 2.0</td><td>ari@northpath.io</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">Apr 2027</td><td class="meta">3d ago</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
<tr><td class="key">KS-PW45-VR82-XA61-9K0L</td><td class="product">Sundial Pro</td><td>tom@workhorse.app</td><td><span class="badge b-danger"><span class="dot" style="background:#B23A3A"></span>Revoked</span></td><td class="meta">—</td><td class="meta">5d ago</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
<tr><td class="key">KS-MN23-LP08-RR54-VV01</td><td class="product">Aurora Plugin</td><td>kate@kate.codes</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">Mar 2027</td><td class="meta">1w ago</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
<tr><td class="key">KS-DD12-XK77-AA98-PQ45</td><td class="product">Sundial 2.0</td><td>raj@spinwheel.app</td><td><span class="badge b-success"><span class="dot" style="background:#2D7A5F"></span>Active</span></td><td class="meta">Mar 2027</td><td class="meta">1w ago</td><td><i data-lucide="more-horizontal" style="color:var(--ink-400)"></i></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script>lucide.createIcons();</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,123 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Keysat — New product</title>
|
||||
<link rel="stylesheet" href="../../colors_and_type.css">
|
||||
<link rel="stylesheet" href="dash.css">
|
||||
<style>
|
||||
.form-grid { display: grid; grid-template-columns: 1fr 380px; gap: 24px; align-items: start; }
|
||||
.panel-stack > * + * { margin-top: 14px; }
|
||||
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
||||
.preview-cert { background: var(--cream-50); border: 1px solid var(--border-1); border-radius: 12px; box-shadow: 0 0 0 1px var(--gold-500) inset, var(--shadow-sm); padding: 22px; }
|
||||
.preview-cert .stamp { font-size: 10px; font-weight: 700; letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold-700); text-align: center; }
|
||||
.preview-cert .h { text-align: center; font-family: var(--font-display); font-weight: 500; font-size: 18px; color: var(--navy-950); margin: 8px 0 4px; }
|
||||
.preview-cert .sub { text-align: center; font-size: 12px; color: var(--ink-500); margin-bottom: 14px; }
|
||||
.preview-cert .field { font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-500); margin-bottom: 3px; }
|
||||
.preview-cert .value { font-family: var(--font-mono); font-size: 13px; color: var(--navy-900); margin-bottom: 10px; }
|
||||
.seg { display: flex; gap: 0; border: 1px solid var(--border-2); border-radius: 7px; overflow: hidden; }
|
||||
.seg button { flex: 1; background: transparent; border: 0; padding: 9px 12px; font-size: 13px; color: var(--ink-700); cursor: pointer; font-family: var(--font-body); border-right: 1px solid var(--border-1); }
|
||||
.seg button:last-child { border-right: 0; }
|
||||
.seg button.on { background: var(--navy-800); color: var(--cream-50); font-weight: 600; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<aside class="sidebar">
|
||||
<div class="brand"><img src="../../assets/keysat-mark.svg" alt=""><span>Keysat</span></div>
|
||||
<a class="nav" href="index.html"><i data-lucide="layout-dashboard"></i>Overview</a>
|
||||
<a class="nav active" href="#"><i data-lucide="package"></i>Products<span class="count">3</span></a>
|
||||
<a class="nav" href="licenses.html"><i data-lucide="key-round"></i>Licenses<span class="count">42</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="users"></i>Customers<span class="count">38</span></a>
|
||||
<a class="nav" href="#"><i data-lucide="tag"></i>Discount codes</a>
|
||||
<div class="group-label">System</div>
|
||||
<a class="nav" href="#"><i data-lucide="scroll-text"></i>Audit log</a>
|
||||
<a class="nav" href="#"><i data-lucide="webhook"></i>Webhooks</a>
|
||||
<a class="nav" href="#"><i data-lucide="settings-2"></i>Settings</a>
|
||||
<div class="footer"><span class="dot"></span><div><div style="color: var(--cream-50); font-weight: 600">BTCPay connected</div></div></div>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<header class="topbar">
|
||||
<div><div class="crumb"><a href="#">Products</a> · New</div><h1>New product</h1></div>
|
||||
<div class="topbar-actions">
|
||||
<button class="btn ghost">Cancel</button>
|
||||
<button class="btn secondary">Save as draft</button>
|
||||
<button class="btn primary"><i data-lucide="check"></i>Create product</button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="form-grid">
|
||||
<div class="panel-stack">
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Product</h3></div>
|
||||
<div style="padding: 18px;">
|
||||
<div class="row-2">
|
||||
<div class="field"><label class="lbl">Product name</label><input class="input" value="Sundial 2.0"><div class="hint">Shown on receipts and the public purchase page.</div></div>
|
||||
<div class="field"><label class="lbl">Slug</label><input class="input mono" value="sundial-2"><div class="hint">Used in your purchase URL.</div></div>
|
||||
</div>
|
||||
<div class="field"><label class="lbl">Tagline</label><input class="input" value="A focused timer for deep work."></div>
|
||||
<div class="field"><label class="lbl">Description</label><textarea class="input" rows="3" style="resize: vertical; font-family: var(--font-body)">Sundial is a calm, single-window timer for deep work sessions. Sound design by Hauschka. macOS, Windows, Linux.</textarea></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Default policy</h3><span class="eyebrow">Drives the public purchase URL</span></div>
|
||||
<div style="padding: 18px;">
|
||||
<div class="row-2">
|
||||
<div class="field"><label class="lbl">Duration</label>
|
||||
<div class="seg">
|
||||
<button>30 days</button><button class="on">1 year</button><button>3 years</button><button>Lifetime</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field"><label class="lbl">Seats</label><input class="input" value="1"><div class="hint">Maximum machines per key.</div></div>
|
||||
</div>
|
||||
<div class="row-2">
|
||||
<div class="field"><label class="lbl">Trial available</label>
|
||||
<div class="seg"><button class="on">14 days</button><button>None</button></div>
|
||||
</div>
|
||||
<div class="field"><label class="lbl">Entitlements</label><input class="input mono" value="core, sync, export"><div class="hint">Comma-separated. Embedded in the signed key.</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-head"><h3>Price</h3></div>
|
||||
<div style="padding: 18px;">
|
||||
<div class="row-2">
|
||||
<div class="field"><label class="lbl">Amount</label><input class="input mono" value="50,000"></div>
|
||||
<div class="field"><label class="lbl">Unit</label>
|
||||
<div class="seg"><button class="on">sats</button><button>BTC</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hint">≈ $30.00 USD at current rate. Updated every 30s from your BTCPay store.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-stack" style="position: sticky; top: 90px;">
|
||||
<div class="eyebrow">Preview</div>
|
||||
<div class="preview-cert">
|
||||
<div class="stamp">— Certificate of License —</div>
|
||||
<div class="h">Sundial 2.0</div>
|
||||
<div class="sub">default · 1 year · single seat</div>
|
||||
<div class="field">License key</div>
|
||||
<div class="value">KS-XXXX-XXXX-XXXX-XXXX</div>
|
||||
<div class="row-2">
|
||||
<div><div class="field">Price</div><div class="value">50,000 sats</div></div>
|
||||
<div><div class="field">Trial</div><div class="value">14 days</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="background: var(--cream-100); padding: 14px 16px; font-size: 12.5px; color: var(--ink-700);">
|
||||
<div style="display: flex; gap: 8px; align-items: start"><i data-lucide="info" style="width: 14px; height: 14px; color: var(--navy-700); flex-shrink: 0; margin-top: 2px;"></i>
|
||||
<span>Your public purchase URL will be<br><code style="font-family: var(--font-mono); color: var(--navy-900); font-size: 12px">aurora.keysat.local/buy/sundial-2</code></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script>lucide.createIcons();</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,36 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Keysat — Sign in</title>
|
||||
<link rel="stylesheet" href="../../colors_and_type.css">
|
||||
<style>
|
||||
body { margin: 0; min-height: 100vh; font-family: var(--font-body); color: var(--ink-900); background: var(--cream-100); background-image: radial-gradient(rgba(14,31,51,0.025) 1px, transparent 1px), radial-gradient(rgba(138,111,61,0.022) 1px, transparent 1px); background-size: 3px 3px, 7px 7px; display: flex; align-items: center; justify-content: center; padding: 40px 20px; }
|
||||
.card { width: 420px; max-width: 100%; background: var(--cream-50); border: 1px solid var(--border-1); border-radius: 14px; box-shadow: 0 0 0 1px var(--gold-500) inset, var(--shadow-md); padding: 36px 36px 32px; position: relative; }
|
||||
.card::before { content: ''; position: absolute; left: 14px; right: 14px; top: 14px; height: 1px; background: var(--gold-500); opacity: 0.4; }
|
||||
.brand { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 6px; }
|
||||
.brand img { width: 56px; height: 56px; }
|
||||
h1 { font-family: var(--font-display); font-weight: 500; font-size: 26px; letter-spacing: -0.02em; color: var(--navy-950); margin: 14px 0 4px; text-align: center; }
|
||||
.sub { text-align: center; font-size: 13.5px; color: var(--ink-500); margin-bottom: 24px; }
|
||||
.lbl { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-700); margin-bottom: 6px; }
|
||||
.input { width: 100%; padding: 11px 13px; font-family: var(--font-mono); font-size: 13px; border: 1px solid var(--border-2); border-radius: 8px; background: white; box-sizing: border-box; }
|
||||
.input:focus { outline: none; border-color: var(--navy-700); box-shadow: 0 0 0 3px rgba(30,58,95,0.18); }
|
||||
.btn { width: 100%; padding: 12px; background: var(--navy-800); color: var(--cream-50); border: 0; border-radius: 8px; font-family: var(--font-body); font-weight: 600; font-size: 14px; cursor: pointer; margin-top: 14px; transition: background 120ms; }
|
||||
.btn:hover { background: var(--navy-900); }
|
||||
.hint { font-size: 12px; color: var(--ink-500); margin-top: 8px; line-height: 1.5; }
|
||||
.footnote { text-align: center; font-size: 12px; color: var(--ink-500); margin-top: 22px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="brand"><img src="../../assets/keysat-mark.svg" alt=""></div>
|
||||
<h1>Keysat admin</h1>
|
||||
<div class="sub">Paste the admin API key from your StartOS service page.</div>
|
||||
<label class="lbl">Admin API key</label>
|
||||
<input class="input" placeholder="ks_admin_…">
|
||||
<div class="hint">Find this in StartOS → Keysat → Properties → adminApiKey.</div>
|
||||
<button class="btn">Sign in</button>
|
||||
<div class="footnote">Connected to <code style="font-family: var(--font-mono); font-size: 11.5px">aurora.keysat.local</code></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user