669 lines
24 KiB
TypeScript
669 lines
24 KiB
TypeScript
|
|
import { DeesElement, html, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
||
|
|
import { idpElementStyles } from './tokens.js';
|
||
|
|
import './idp-badge.js';
|
||
|
|
import './idp-button.js';
|
||
|
|
import './idp-icon.js';
|
||
|
|
import './idp-landing-hero.js';
|
||
|
|
|
||
|
|
declare global {
|
||
|
|
interface HTMLElementTagNameMap {
|
||
|
|
'idp-landing-page': IdpLandingPage;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@customElement('idp-landing-page')
|
||
|
|
export class IdpLandingPage extends DeesElement {
|
||
|
|
public static demo = () => html`<idp-landing-page></idp-landing-page>`;
|
||
|
|
public static demoGroups = ['idp.global v3 full pages'];
|
||
|
|
|
||
|
|
public static styles = [
|
||
|
|
...idpElementStyles,
|
||
|
|
css`
|
||
|
|
:host {
|
||
|
|
display: block;
|
||
|
|
--idp-bg: #0a0a0a;
|
||
|
|
--idp-bg-2: #111111;
|
||
|
|
--idp-card: #121212;
|
||
|
|
--idp-card-2: #161616;
|
||
|
|
--idp-fg: #fafafa;
|
||
|
|
--idp-fg-2: #d4d4d8;
|
||
|
|
--idp-fg-3: hsl(0 0% 70%);
|
||
|
|
--idp-muted-fg: hsl(0 0% 55%);
|
||
|
|
--idp-border: #262626;
|
||
|
|
--idp-border-soft: #1c1c1c;
|
||
|
|
--idp-border-strong: #333333;
|
||
|
|
--idp-accent: #3b82f6;
|
||
|
|
--idp-accent-hover: #60a5fa;
|
||
|
|
background: var(--idp-bg);
|
||
|
|
color: var(--idp-fg);
|
||
|
|
}
|
||
|
|
.page {
|
||
|
|
min-height: 100vh;
|
||
|
|
background: var(--idp-bg);
|
||
|
|
}
|
||
|
|
nav {
|
||
|
|
position: sticky;
|
||
|
|
top: 0;
|
||
|
|
z-index: 20;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
gap: 24px;
|
||
|
|
height: 56px;
|
||
|
|
max-width: 1240px;
|
||
|
|
margin: 0 auto;
|
||
|
|
padding: 0 32px;
|
||
|
|
border-bottom: 1px solid var(--idp-border-soft);
|
||
|
|
background: rgba(10,10,10,0.86);
|
||
|
|
backdrop-filter: blur(14px) saturate(140%);
|
||
|
|
}
|
||
|
|
.nav-shell {
|
||
|
|
position: sticky;
|
||
|
|
top: 0;
|
||
|
|
z-index: 20;
|
||
|
|
border-bottom: 1px solid var(--idp-border-soft);
|
||
|
|
background: rgba(10,10,10,0.86);
|
||
|
|
}
|
||
|
|
.logo {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
font-family: var(--idp-display);
|
||
|
|
font-size: 16px;
|
||
|
|
font-weight: 700;
|
||
|
|
letter-spacing: -0.015em;
|
||
|
|
}
|
||
|
|
.logo-dot {
|
||
|
|
width: 6px;
|
||
|
|
height: 6px;
|
||
|
|
border-radius: 999px;
|
||
|
|
background: var(--idp-accent);
|
||
|
|
box-shadow: 0 0 12px var(--idp-accent);
|
||
|
|
}
|
||
|
|
.links, .actions {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
}
|
||
|
|
.links a {
|
||
|
|
padding: 6px 12px;
|
||
|
|
border-radius: 5px;
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-size: 13px;
|
||
|
|
text-decoration: none;
|
||
|
|
}
|
||
|
|
.links a:hover {
|
||
|
|
background: rgba(255,255,255,0.04);
|
||
|
|
color: var(--idp-fg);
|
||
|
|
}
|
||
|
|
.status {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
margin-right: 8px;
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
}
|
||
|
|
.live-dot {
|
||
|
|
width: 6px;
|
||
|
|
height: 6px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: var(--idp-ok);
|
||
|
|
box-shadow: 0 0 8px var(--idp-ok);
|
||
|
|
}
|
||
|
|
.wrap {
|
||
|
|
max-width: 1240px;
|
||
|
|
margin: 0 auto;
|
||
|
|
padding: 0 32px;
|
||
|
|
}
|
||
|
|
.proof, .section, .manifesto, .cta, footer {
|
||
|
|
border-bottom: 1px solid var(--idp-border-soft);
|
||
|
|
}
|
||
|
|
.proof {
|
||
|
|
padding: 56px 0;
|
||
|
|
}
|
||
|
|
.proof-label {
|
||
|
|
margin-bottom: 28px;
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
text-align: center;
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
letter-spacing: 0.12em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
.proof-row {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(6, 1fr);
|
||
|
|
gap: 24px;
|
||
|
|
place-items: center;
|
||
|
|
opacity: 0.72;
|
||
|
|
}
|
||
|
|
.proof-name {
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-family: var(--idp-display);
|
||
|
|
font-size: 18px;
|
||
|
|
font-weight: 700;
|
||
|
|
letter-spacing: -0.02em;
|
||
|
|
}
|
||
|
|
.section {
|
||
|
|
padding: 120px 0;
|
||
|
|
}
|
||
|
|
.section.alt {
|
||
|
|
background: var(--idp-bg-2);
|
||
|
|
}
|
||
|
|
.section-head {
|
||
|
|
max-width: 760px;
|
||
|
|
margin: 0 auto 64px;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
.eyebrow {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
margin-bottom: 16px;
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
letter-spacing: 0.1em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
.eyebrow::before, .eyebrow::after {
|
||
|
|
content: '';
|
||
|
|
width: 24px;
|
||
|
|
height: 1px;
|
||
|
|
background: var(--idp-border-strong);
|
||
|
|
}
|
||
|
|
h2, h3, q {
|
||
|
|
margin: 0;
|
||
|
|
font-family: var(--idp-display);
|
||
|
|
letter-spacing: -0.03em;
|
||
|
|
}
|
||
|
|
h2 {
|
||
|
|
font-size: clamp(36px, 4.5vw, 56px);
|
||
|
|
line-height: 1.05;
|
||
|
|
}
|
||
|
|
em {
|
||
|
|
color: var(--idp-accent-hover);
|
||
|
|
font-family: var(--idp-serif);
|
||
|
|
font-style: italic;
|
||
|
|
font-weight: 400;
|
||
|
|
}
|
||
|
|
.lede {
|
||
|
|
max-width: 640px;
|
||
|
|
margin: 20px auto 0;
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-size: 17px;
|
||
|
|
line-height: 1.55;
|
||
|
|
}
|
||
|
|
.bento {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(6, 1fr);
|
||
|
|
gap: 16px;
|
||
|
|
}
|
||
|
|
.tile, .tier, .chain-panel, .terminal {
|
||
|
|
border: 1px solid var(--idp-border-soft);
|
||
|
|
border-radius: 12px;
|
||
|
|
background: var(--idp-bg-2);
|
||
|
|
}
|
||
|
|
.tile {
|
||
|
|
padding: 28px;
|
||
|
|
}
|
||
|
|
.tile.col-2 { grid-column: span 2; }
|
||
|
|
.tile.col-3 { grid-column: span 3; }
|
||
|
|
.tile.tall { grid-row: span 2; }
|
||
|
|
.tile-tag {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
margin-bottom: 14px;
|
||
|
|
color: var(--idp-accent-hover);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 10.5px;
|
||
|
|
font-weight: 600;
|
||
|
|
letter-spacing: 0.06em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
.tile-tag::before {
|
||
|
|
content: '';
|
||
|
|
width: 6px;
|
||
|
|
height: 6px;
|
||
|
|
border-radius: 999px;
|
||
|
|
background: var(--idp-accent);
|
||
|
|
}
|
||
|
|
.tile h3 {
|
||
|
|
margin-bottom: 10px;
|
||
|
|
font-size: 24px;
|
||
|
|
line-height: 1.15;
|
||
|
|
}
|
||
|
|
.tile p, .tier li, .chain-step p {
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-size: 14px;
|
||
|
|
line-height: 1.55;
|
||
|
|
}
|
||
|
|
.approval-stack {
|
||
|
|
display: grid;
|
||
|
|
gap: 6px;
|
||
|
|
margin-top: 22px;
|
||
|
|
}
|
||
|
|
.approval-row {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 28px 1fr auto;
|
||
|
|
gap: 12px;
|
||
|
|
align-items: center;
|
||
|
|
padding: 10px 12px;
|
||
|
|
border: 1px solid var(--idp-border-soft);
|
||
|
|
border-left: 2px solid var(--idp-accent);
|
||
|
|
border-radius: 6px;
|
||
|
|
background: var(--idp-bg);
|
||
|
|
}
|
||
|
|
.avatar {
|
||
|
|
width: 28px;
|
||
|
|
height: 28px;
|
||
|
|
display: grid;
|
||
|
|
place-items: center;
|
||
|
|
border: 1px solid var(--idp-border);
|
||
|
|
border-radius: 50%;
|
||
|
|
background: var(--idp-card-2);
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
.approval-row strong {
|
||
|
|
display: block;
|
||
|
|
color: var(--idp-fg);
|
||
|
|
font-size: 12.5px;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
.approval-row span.meta {
|
||
|
|
color: color-mix(in srgb, var(--idp-muted-fg), transparent 30%);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 10.5px;
|
||
|
|
}
|
||
|
|
.identity-card {
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
margin-top: 22px;
|
||
|
|
border: 1px solid var(--idp-border);
|
||
|
|
border-radius: 10px;
|
||
|
|
padding: 20px;
|
||
|
|
background: linear-gradient(140deg, #1a1a1a 0%, #0a0a0a 100%);
|
||
|
|
}
|
||
|
|
.identity-card::after {
|
||
|
|
content: '';
|
||
|
|
position: absolute;
|
||
|
|
top: -100px;
|
||
|
|
right: -80px;
|
||
|
|
width: 240px;
|
||
|
|
height: 240px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: radial-gradient(circle, rgba(0,105,242,0.4), transparent 65%);
|
||
|
|
}
|
||
|
|
.identity-card > * {
|
||
|
|
position: relative;
|
||
|
|
z-index: 1;
|
||
|
|
}
|
||
|
|
.chip {
|
||
|
|
width: 32px;
|
||
|
|
height: 24px;
|
||
|
|
margin: 18px 0 14px;
|
||
|
|
border-radius: 3px;
|
||
|
|
background: linear-gradient(135deg, #93bbfd 0%, #0050b9 80%);
|
||
|
|
}
|
||
|
|
.mono {
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 10.5px;
|
||
|
|
}
|
||
|
|
.metric {
|
||
|
|
margin-top: 8px;
|
||
|
|
background: linear-gradient(180deg, var(--idp-fg) 0%, var(--idp-muted-fg) 110%);
|
||
|
|
background-clip: text;
|
||
|
|
color: transparent;
|
||
|
|
font-family: var(--idp-display);
|
||
|
|
font-size: 64px;
|
||
|
|
font-weight: 700;
|
||
|
|
letter-spacing: -0.04em;
|
||
|
|
line-height: 1;
|
||
|
|
}
|
||
|
|
.metric span {
|
||
|
|
font-size: 24px;
|
||
|
|
}
|
||
|
|
.devices-row {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(4, 1fr);
|
||
|
|
gap: 8px;
|
||
|
|
margin-top: 22px;
|
||
|
|
}
|
||
|
|
.dev-cell {
|
||
|
|
padding: 14px 10px;
|
||
|
|
border: 1px solid var(--idp-border-soft);
|
||
|
|
border-radius: 6px;
|
||
|
|
background: var(--idp-bg);
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
.dev-icon {
|
||
|
|
width: 32px;
|
||
|
|
height: 32px;
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
margin-bottom: 8px;
|
||
|
|
border: 1px solid rgba(96,165,250,0.35);
|
||
|
|
border-radius: 9px;
|
||
|
|
color: var(--idp-accent-hover);
|
||
|
|
}
|
||
|
|
.dev-name {
|
||
|
|
color: var(--idp-fg);
|
||
|
|
font-size: 12px;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
.dev-sub {
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
}
|
||
|
|
.chain-grid, .dev-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
gap: 48px;
|
||
|
|
}
|
||
|
|
.chain-steps {
|
||
|
|
display: grid;
|
||
|
|
gap: 28px;
|
||
|
|
}
|
||
|
|
.chain-step {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 70px 1fr;
|
||
|
|
gap: 16px;
|
||
|
|
padding-bottom: 24px;
|
||
|
|
border-bottom: 1px solid var(--idp-border-soft);
|
||
|
|
}
|
||
|
|
.chain-step > div {
|
||
|
|
color: var(--idp-accent-hover);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
font-weight: 600;
|
||
|
|
letter-spacing: 0.08em;
|
||
|
|
}
|
||
|
|
.chain-panel {
|
||
|
|
overflow: hidden;
|
||
|
|
background: var(--idp-bg);
|
||
|
|
}
|
||
|
|
.chain-head {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 14px 18px;
|
||
|
|
border-bottom: 1px solid var(--idp-border-soft);
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
letter-spacing: 0.08em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
.chain-block {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: auto 1fr auto;
|
||
|
|
gap: 12px;
|
||
|
|
margin: 8px 14px;
|
||
|
|
padding: 14px 16px;
|
||
|
|
border: 1px solid var(--idp-border-soft);
|
||
|
|
border-radius: 8px;
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
}
|
||
|
|
.chain-block.idp {
|
||
|
|
border-left: 2px solid var(--idp-accent);
|
||
|
|
background: rgba(0,80,185,0.08);
|
||
|
|
}
|
||
|
|
.tiers {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(3, 1fr);
|
||
|
|
gap: 16px;
|
||
|
|
}
|
||
|
|
.tier {
|
||
|
|
position: relative;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
padding: 28px;
|
||
|
|
}
|
||
|
|
.tier.featured {
|
||
|
|
border-color: var(--idp-accent);
|
||
|
|
background: linear-gradient(180deg, rgba(59,130,246,0.06) 0%, var(--idp-bg-2) 40%);
|
||
|
|
}
|
||
|
|
.tier-name {
|
||
|
|
margin-bottom: 10px;
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
letter-spacing: 0.08em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
.price {
|
||
|
|
margin: 12px 0 20px;
|
||
|
|
font-family: var(--idp-display);
|
||
|
|
font-size: 40px;
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
.tier ul {
|
||
|
|
flex: 1;
|
||
|
|
margin: 0 0 24px;
|
||
|
|
padding-left: 20px;
|
||
|
|
}
|
||
|
|
.dev-text p {
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
}
|
||
|
|
.tags {
|
||
|
|
display: flex;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
gap: 6px;
|
||
|
|
margin: 18px 0 22px;
|
||
|
|
}
|
||
|
|
.tags span {
|
||
|
|
padding: 4px 10px;
|
||
|
|
border: 1px solid var(--idp-border);
|
||
|
|
border-radius: 999px;
|
||
|
|
background: var(--idp-bg-2);
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 10.5px;
|
||
|
|
}
|
||
|
|
.terminal {
|
||
|
|
overflow: hidden;
|
||
|
|
background: var(--idp-bg);
|
||
|
|
}
|
||
|
|
.term-bar {
|
||
|
|
display: flex;
|
||
|
|
gap: 6px;
|
||
|
|
padding: 10px 14px;
|
||
|
|
border-bottom: 1px solid var(--idp-border-soft);
|
||
|
|
}
|
||
|
|
.tdot {
|
||
|
|
width: 11px;
|
||
|
|
height: 11px;
|
||
|
|
border-radius: 50%;
|
||
|
|
}
|
||
|
|
.red { background: #ff5f57; }
|
||
|
|
.yellow { background: #ffbd2e; }
|
||
|
|
.green { background: #28c840; }
|
||
|
|
pre {
|
||
|
|
min-height: 300px;
|
||
|
|
margin: 0;
|
||
|
|
padding: 22px 24px;
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 13px;
|
||
|
|
line-height: 1.85;
|
||
|
|
}
|
||
|
|
.manifesto, .cta {
|
||
|
|
padding: 120px 0;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
q {
|
||
|
|
display: block;
|
||
|
|
max-width: 980px;
|
||
|
|
margin: 0 auto;
|
||
|
|
font-family: var(--idp-serif);
|
||
|
|
font-size: clamp(32px, 4vw, 48px);
|
||
|
|
font-style: italic;
|
||
|
|
line-height: 1.2;
|
||
|
|
quotes: none;
|
||
|
|
}
|
||
|
|
q::before, q::after {
|
||
|
|
content: none;
|
||
|
|
}
|
||
|
|
.cta {
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
.cta::before {
|
||
|
|
content: '';
|
||
|
|
position: absolute;
|
||
|
|
left: 50%;
|
||
|
|
top: 50%;
|
||
|
|
width: 800px;
|
||
|
|
height: 600px;
|
||
|
|
transform: translate(-50%, -50%);
|
||
|
|
background: radial-gradient(ellipse, rgba(59,130,246,0.15) 0%, transparent 60%);
|
||
|
|
}
|
||
|
|
.cta .wrap {
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
.cta p {
|
||
|
|
max-width: 560px;
|
||
|
|
margin: 24px auto 32px;
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
}
|
||
|
|
footer {
|
||
|
|
padding: 64px 0 28px;
|
||
|
|
border-bottom: 0;
|
||
|
|
}
|
||
|
|
.footer-cols {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 2fr 1fr 1fr 1fr;
|
||
|
|
gap: 48px;
|
||
|
|
margin-bottom: 48px;
|
||
|
|
}
|
||
|
|
.footer-brand p, .footer-col a, .footer-bottom {
|
||
|
|
color: var(--idp-muted-fg);
|
||
|
|
font-size: 13px;
|
||
|
|
}
|
||
|
|
.footer-col {
|
||
|
|
display: grid;
|
||
|
|
gap: 9px;
|
||
|
|
}
|
||
|
|
.footer-col h4 {
|
||
|
|
margin: 0;
|
||
|
|
color: var(--idp-fg-3);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
letter-spacing: 0.1em;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
.footer-bottom {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding-top: 22px;
|
||
|
|
border-top: 1px solid var(--idp-border-soft);
|
||
|
|
font-family: var(--idp-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
}
|
||
|
|
@media (max-width: 1100px) {
|
||
|
|
.links { display: none; }
|
||
|
|
.bento { grid-template-columns: repeat(2, 1fr); }
|
||
|
|
.tile.col-2, .tile.col-3 { grid-column: span 2; }
|
||
|
|
.chain-grid, .dev-grid { grid-template-columns: 1fr; }
|
||
|
|
.tiers { grid-template-columns: 1fr; max-width: 520px; margin: 0 auto; }
|
||
|
|
.footer-cols { grid-template-columns: 1fr 1fr; }
|
||
|
|
}
|
||
|
|
@media (max-width: 720px) {
|
||
|
|
nav, .wrap { padding-left: 20px; padding-right: 20px; }
|
||
|
|
.status, .actions .ghost { display: none; }
|
||
|
|
.proof-row { grid-template-columns: repeat(2, 1fr); }
|
||
|
|
.bento { grid-template-columns: 1fr; }
|
||
|
|
.tile.col-2, .tile.col-3 { grid-column: span 1; }
|
||
|
|
.section, .manifesto, .cta { padding: 80px 0; }
|
||
|
|
.footer-cols { grid-template-columns: 1fr; }
|
||
|
|
}
|
||
|
|
`,
|
||
|
|
];
|
||
|
|
|
||
|
|
private renderNav() {
|
||
|
|
return html`
|
||
|
|
<div class="nav-shell">
|
||
|
|
<nav>
|
||
|
|
<div class="logo">idp<span class="logo-dot"></span>global</div>
|
||
|
|
<div class="links"><a href="#product">Product</a><a href="#features">Features</a><a href="#chain">On-chain</a><a href="#pricing">Pricing</a><a href="#developers">Developers</a></div>
|
||
|
|
<div class="actions"><span class="status"><span class="live-dot"></span>All systems normal</span><idp-button variant="ghost" size="sm">Sign in</idp-button><idp-button variant="accent" size="sm">Claim identity</idp-button></div>
|
||
|
|
</nav>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
|
||
|
|
private renderFeatures() {
|
||
|
|
return html`
|
||
|
|
<section class="section" id="features">
|
||
|
|
<div class="wrap">
|
||
|
|
<div class="section-head"><div class="eyebrow">Capabilities</div><h2>Native on every screen <em>you already carry.</em></h2><p class="lede">Approvals on iPhone. Tap-to-auth via NFC. Lock-screen actions on Apple Watch. The same identity, one tap away on any device.</p></div>
|
||
|
|
<div class="bento">
|
||
|
|
<div class="tile col-3 tall"><div class="tile-tag">Push approvals</div><h3>Approve or deny <em>in one tap.</em></h3><p>Every login, OAuth grant, and sensitive action triggers a real-time approval.</p><div class="approval-stack">${['GitHub OAuth|repo:read - 2 min ago|approved|ok', 'CLI login - MacBook Pro|Berlin - just now|pending|accent', 'Unknown device|Lagos - 1 hr ago|denied|error', 'NFC tap - door 4F|HQ - 12 min ago|approved|ok'].map((rowArg) => { const row = rowArg.split('|'); return html`<div class="approval-row"><div class="avatar">${row[0].slice(0,2).toUpperCase()}</div><div><strong>${row[0]}</strong><span class="meta">${row[1]}</span></div><idp-badge variant=${row[3] as any}>${row[2]}</idp-badge></div>`; })}</div></div>
|
||
|
|
<div class="tile col-3"><div class="tile-tag">NFC tap-to-auth</div><h3>Tap to <em>authenticate.</em></h3><p>Hold your phone to any compatible reader. Identity token exchanges in under a second.</p><div class="identity-card"><h3>Alex Mercer</h3><div class="mono">@alexmercer - Personal</div><div class="chip"></div><div class="mono">did:idp:0x4a3f...c819</div></div></div>
|
||
|
|
<div class="tile col-3"><div class="tile-tag">Four platforms</div><h3>iPhone, Watch, iPad, Mac.</h3><p>Every device you carry is a trusted authenticator.</p><div class="devices-row">${[
|
||
|
|
['iPhone', 'phone'],
|
||
|
|
['Watch', 'smartphone-nfc'],
|
||
|
|
['iPad', 'device'],
|
||
|
|
['Mac', 'monitor'],
|
||
|
|
].map((deviceArg) => html`<div class="dev-cell"><div class="dev-icon"><idp-icon name=${deviceArg[1] as any} size="18"></idp-icon></div><div class="dev-name">${deviceArg[0]}</div><div class="dev-sub">trusted</div></div>`)}</div><div class="mono" style="margin-top:14px">One approval, anywhere - synchronized end-to-end.</div></div>
|
||
|
|
<div class="tile col-2"><div class="tile-tag">Average approval</div><h3>Sub-second auth.</h3><p>Push delivery, biometric prompt, and signed response under a second.</p><div class="metric">0.8<span>sec</span></div></div>
|
||
|
|
<div class="tile col-2"><div class="tile-tag">Audit-grade</div><h3>Every action, <em>on the record.</em></h3><p>Tamper-evident audit trail per identity and organization.</p></div>
|
||
|
|
<div class="tile col-2"><div class="tile-tag">Recovery</div><h3>Lose a phone? Not your identity.</h3><p>Multi-device recovery or social-recovery quorum. No vendor lockout.</p></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
|
||
|
|
private renderChain() {
|
||
|
|
return html`
|
||
|
|
<section class="section alt" id="chain"><div class="wrap"><div class="section-head"><div class="eyebrow">Cardano-anchored</div><h2>Your identity outlives <em>any single server.</em></h2><p class="lede">Every identity is anchored to the Cardano mainnet, independently verifiable and recoverable.</p></div><div class="chain-grid"><div class="chain-steps">${[['01 / 03', 'Immutable record', 'Your identity hash is written to Cardano at creation and on every key rotation.'], ['02 / 03', 'Synced on every change', 'Profile updates, device additions, and revocations are anchored to the chain.'], ['03 / 03', 'Independently verifiable', 'Any compatible resolver can verify your identity directly against the public ledger.']].map((stepArg) => html`<div class="chain-step"><div>${stepArg[0]}</div><section><h3>${stepArg[1]}</h3><p>${stepArg[2]}</p></section></div>`)}</div><div class="chain-panel"><div class="chain-head"><span>Cardano mainnet</span><idp-badge variant="accent">live</idp-badge></div>${['#9 841 220', '#9 841 221', '#9 841 222', '#9 841 223'].map((blockArg, indexArg) => html`<div class="chain-block ${indexArg === 1 || indexArg === 2 ? 'idp' : ''}"><span>${blockArg}</span><span>${indexArg === 1 ? 'did:idp:0x4a3f...c819' : indexArg === 2 ? 'did:idp:0x9b12...f034' : 'confirmed block'}</span><strong>${indexArg === 1 || indexArg === 2 ? 'idp.global' : 'confirmed'}</strong></div>`)}</div></div></div></section>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
|
||
|
|
private renderPricing() {
|
||
|
|
const tiers = [
|
||
|
|
['Personal', 'For one person.', '$0', ['One portable identity', 'Push approval on devices', 'NFC tap-to-authenticate', 'Anchored on Cardano'], 'Claim your identity'],
|
||
|
|
['Family & Org', 'For teams under 1,000.', '$0', ['Multi-member organization', 'Role-based access control', 'Shared OAuth client registry', 'Full audit trail'], 'Start an organization'],
|
||
|
|
['Enterprise', 'Above $1M ARR.', 'Fair', ['Self-hosted and air-gap deployable', 'Compliance and audit support', 'Global admin across orgs', 'Priority SLA'], 'Talk to us'],
|
||
|
|
];
|
||
|
|
return html`<section class="section" id="pricing"><div class="wrap"><div class="section-head"><div class="eyebrow">Pricing</div><h2>The same identity, <em>at every scale.</em></h2><p class="lede">Free for the first thousand users. Fair contribution above that. No hard paywalls.</p></div><div class="tiers">${tiers.map((tierArg, indexArg) => html`<div class="tier ${indexArg === 1 ? 'featured' : ''}"><div class="tier-name">${tierArg[0]}</div><h3>${tierArg[1]}</h3><div class="price">${tierArg[2]}</div><ul>${(tierArg[3] as string[]).map((itemArg) => html`<li>${itemArg}</li>`)}</ul><idp-button variant=${indexArg === 1 ? 'accent' : 'ghost'}>${tierArg[4]}</idp-button></div>`)}</div></div></section>`;
|
||
|
|
}
|
||
|
|
|
||
|
|
private renderDevelopers() {
|
||
|
|
return html`
|
||
|
|
<section class="section alt" id="developers"><div class="wrap dev-grid"><div class="dev-text"><div class="eyebrow">For developers</div><h2>No black boxes <em>in your identity stack.</em></h2><p>idp.global is fully open source and MIT licensed. Read the cryptography. Verify the Cardano sync. Run it on your own metal.</p><div class="tags">${['MIT licensed', 'OAuth 2 / OIDC', 'Self-hostable', 'Air-gappable', 'Cardano native', 'SOC 2'].map((tagArg) => html`<span>${tagArg}</span>`)}</div><idp-button variant="accent">View source</idp-button></div><div class="terminal"><div class="term-bar"><span class="tdot red"></span><span class="tdot yellow"></span><span class="tdot green"></span></div><pre><code>$ idp identity create
|
||
|
|
OK Identity created - did:idp:0x4a3f...c819
|
||
|
|
OK Confirmed on-chain - permanent
|
||
|
|
|
||
|
|
$ idp login github.com
|
||
|
|
OK Push sent - iPhone 15 Pro
|
||
|
|
OK Approved - Watch - 0.8s</code></pre></div></div></section>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
|
||
|
|
public render(): TemplateResult {
|
||
|
|
return html`
|
||
|
|
<div class="page">
|
||
|
|
${this.renderNav()}
|
||
|
|
<idp-landing-hero></idp-landing-hero>
|
||
|
|
<section class="proof"><div class="wrap"><div class="proof-label">Built for identity at every scale</div><div class="proof-row">${['Open Source', 'Self-hostable', 'Cardano anchored', 'OIDC ready', 'Passkey first', 'Free for everyone'].map((nameArg) => html`<div class="proof-name">${nameArg}</div>`)}</div></div></section>
|
||
|
|
${this.renderFeatures()}${this.renderChain()}${this.renderPricing()}${this.renderDevelopers()}
|
||
|
|
<section class="manifesto"><div class="wrap"><div class="eyebrow">Why we built this</div><q>Identity should not be a product the user is sold.<br/>It should be a permanent <em>fact</em>, owned by the person it describes.</q></div></section>
|
||
|
|
<section class="cta"><div class="wrap"><h2>Claim your identity.<br/><em>Free, forever.</em></h2><p>Sixty seconds to claim, anchored to Cardano on submission. No credit card. No vendor lock-in.</p><idp-button variant="accent" size="lg">Claim your identity</idp-button></div></section>
|
||
|
|
<footer><div class="wrap"><div class="footer-cols"><div class="footer-brand"><div class="logo">idp<span class="logo-dot"></span>global</div><p>An open identity provider for everyone. Anchored on Cardano. Built in the open. Yours forever.</p></div><div class="footer-col"><h4>Product</h4><a>For individuals</a><a>For organizations</a><a>Cardano sync</a></div><div class="footer-col"><h4>Developers</h4><a>Documentation</a><a>Self-hosting</a><a>SDKs</a></div><div class="footer-col"><h4>Company</h4><a>Manifesto</a><a>Security</a><a>Privacy</a></div></div><div class="footer-bottom"><span>© 2026 idp.global - MIT - Anchored to Cardano</span><span>Source - Community</span></div></div></footer>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
}
|