feat: add Lumina AI assistant landing page
This commit is contained in:
+25
-2
@@ -216,7 +216,7 @@
|
||||
<header>
|
||||
<span class="eyebrow">Web Development</span>
|
||||
<h1>Портфолио</h1>
|
||||
<p>6 лендинговых страниц — резюме и аренда недвижимости</p>
|
||||
<p>7 лендинговых страниц — резюме, аренда недвижимости и AI-ассистент</p>
|
||||
</header>
|
||||
|
||||
<!-- ── Resume section ── -->
|
||||
@@ -325,8 +325,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── AI Assistant section ── -->
|
||||
<div class="section-wrap">
|
||||
<div class="section-label">AI-ассистент</div>
|
||||
<div class="grid">
|
||||
|
||||
<a class="card" href="lumina/" style="--c-accent: var(--accent-1)">
|
||||
<div class="card-header">
|
||||
<div class="card-icon">◉</div>
|
||||
<span class="card-tag">AI</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-title">Lumina</div>
|
||||
<div class="card-desc">Космический лендинг для AI-ассистента — нейронные сети, светящиеся частицы, философский дизайн.</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span>lumina/</span>
|
||||
<span class="arrow">→</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>6 лендингов · Emil Shanaty · 2026</p>
|
||||
<p>7 лендингов · Emil Shanaty · 2026</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,940 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Lumina — Consciousness in Digital Form</title>
|
||||
<meta name="description" content="Lumina is an AI assistant that thinks before it speaks. Built for depth, not speed." />
|
||||
<style>
|
||||
/* ─── Tokens ─────────────────────────────────────────────── */
|
||||
:root {
|
||||
--bg-0: #04020d;
|
||||
--bg-1: #080516;
|
||||
--bg-2: #0d0a22;
|
||||
--bg-3: #12102e;
|
||||
|
||||
--accent: #a78bfa; /* soft violet */
|
||||
--accent-dim: #7c5fe6;
|
||||
--accent-glow: rgba(167, 139, 250, 0.18);
|
||||
--accent-halo: rgba(167, 139, 250, 0.06);
|
||||
|
||||
--text-1: #f0eeff;
|
||||
--text-2: #b8b0d8;
|
||||
--text-3: #7a7294;
|
||||
--text-4: #4a4468;
|
||||
|
||||
--border: rgba(167, 139, 250, 0.12);
|
||||
--radius: 6px;
|
||||
|
||||
--font-sans: system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
--font-mono: "SF Mono", "Fira Code", "Cascadia Code", Consolas, monospace;
|
||||
|
||||
--easing: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
/* ─── Reset ──────────────────────────────────────────────── */
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
html { scroll-behavior: smooth; font-size: 16px; }
|
||||
|
||||
body {
|
||||
background-color: var(--bg-0);
|
||||
color: var(--text-2);
|
||||
font-family: var(--font-sans);
|
||||
line-height: 1.7;
|
||||
overflow-x: hidden;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* ─── Canvas background ──────────────────────────────────── */
|
||||
#neural-canvas {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
/* ─── Layout ─────────────────────────────────────────────── */
|
||||
.site-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: min(720px, 100% - 3rem);
|
||||
margin-inline: auto;
|
||||
padding-block: 1rem;
|
||||
}
|
||||
|
||||
section {
|
||||
padding-block: clamp(4rem, 10vw, 8rem);
|
||||
}
|
||||
|
||||
/* ─── Nav ────────────────────────────────────────────────── */
|
||||
nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
padding-block: 1.25rem;
|
||||
background: linear-gradient(to bottom, var(--bg-0) 60%, transparent);
|
||||
}
|
||||
|
||||
nav .container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-block: 0;
|
||||
}
|
||||
|
||||
.nav-logo {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-1);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-logo span {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: var(--text-3);
|
||||
text-decoration: none;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 0.06em;
|
||||
transition: color 0.2s var(--easing);
|
||||
}
|
||||
|
||||
.nav-links a:hover,
|
||||
.nav-links a:focus-visible {
|
||||
color: var(--accent);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.nav-links { display: none; }
|
||||
}
|
||||
|
||||
/* ─── Hero ───────────────────────────────────────────────── */
|
||||
#hero {
|
||||
min-height: calc(100svh - 4rem);
|
||||
display: grid;
|
||||
align-items: center;
|
||||
padding-block: 0;
|
||||
}
|
||||
|
||||
#hero .container {
|
||||
display: grid;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
.hero-label {
|
||||
display: inline-block;
|
||||
font-size: 0.72rem;
|
||||
font-family: var(--font-mono);
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(3.5rem, 10vw, 7rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 0.95;
|
||||
color: var(--text-1);
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
oklch(95% 0.04 280) 0%,
|
||||
oklch(82% 0.18 295) 40%,
|
||||
oklch(72% 0.22 255) 80%,
|
||||
oklch(60% 0.14 235) 100%
|
||||
);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Fallback for browsers without oklch */
|
||||
@supports not (color: oklch(50% 0.1 180)) {
|
||||
h1 {
|
||||
background: linear-gradient(135deg, #e8e0ff 0%, #a78bfa 40%, #818cf8 80%, #6366f1 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-tagline {
|
||||
font-size: clamp(1.1rem, 2.5vw, 1.4rem);
|
||||
color: var(--text-2);
|
||||
line-height: 1.5;
|
||||
max-width: 44ch;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.hero-tagline em {
|
||||
font-style: normal;
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
/* ─── CTA Button ─────────────────────────────────────────── */
|
||||
.btn-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.6em;
|
||||
padding: 0.85em 2em;
|
||||
min-height: 44px;
|
||||
background: transparent;
|
||||
border: 1px solid var(--accent-dim);
|
||||
border-radius: var(--radius);
|
||||
color: var(--accent);
|
||||
font-size: 0.92rem;
|
||||
font-family: var(--font-sans);
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.06em;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
color 0.25s var(--easing),
|
||||
border-color 0.25s var(--easing),
|
||||
box-shadow 0.25s var(--easing);
|
||||
}
|
||||
|
||||
.btn-primary::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: var(--accent);
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s var(--easing);
|
||||
}
|
||||
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus-visible {
|
||||
color: var(--bg-0);
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 28px var(--accent-glow), 0 0 60px var(--accent-halo);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.btn-primary:hover::before,
|
||||
.btn-primary:focus-visible::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.btn-primary span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.btn-arrow {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: inline-block;
|
||||
transition: transform 0.2s var(--easing);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.btn-primary:hover .btn-arrow,
|
||||
.btn-primary:focus-visible .btn-arrow {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
/* ─── Section titles ─────────────────────────────────────── */
|
||||
.section-label {
|
||||
font-size: 0.68rem;
|
||||
font-family: var(--font-mono);
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
opacity: 0.7;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: clamp(1.6rem, 4vw, 2.4rem);
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.2;
|
||||
color: var(--text-1);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: clamp(1.05rem, 2vw, 1.2rem);
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.01em;
|
||||
color: var(--text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--text-2);
|
||||
max-width: 60ch;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* ─── Divider ────────────────────────────────────────────── */
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: linear-gradient(to right, transparent, var(--border), transparent);
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* ─── What It Is section ─────────────────────────────────── */
|
||||
#what .container {
|
||||
display: grid;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
#what p {
|
||||
font-size: clamp(1rem, 2vw, 1.15rem);
|
||||
line-height: 1.8;
|
||||
max-width: 56ch;
|
||||
}
|
||||
|
||||
#what p strong {
|
||||
color: var(--text-1);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* ─── Capabilities ───────────────────────────────────────── */
|
||||
#capabilities .container {
|
||||
display: grid;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.caps-grid {
|
||||
display: grid;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
.cap-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 0 1.5rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.cap-number {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
color: var(--accent);
|
||||
opacity: 0.6;
|
||||
padding-top: 0.35rem;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.cap-item h3 {
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.cap-item p {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.7;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/* ─── Philosophy ─────────────────────────────────────────── */
|
||||
#philosophy {
|
||||
background: linear-gradient(to bottom, transparent, var(--bg-1) 30%, var(--bg-1) 70%, transparent);
|
||||
}
|
||||
|
||||
#philosophy .container {
|
||||
display: grid;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 2px solid var(--accent);
|
||||
padding-left: 2rem;
|
||||
display: grid;
|
||||
gap: 1.2rem;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
font-size: clamp(1.15rem, 2.5vw, 1.45rem);
|
||||
line-height: 1.6;
|
||||
font-weight: 300;
|
||||
color: var(--text-1);
|
||||
max-width: 48ch;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
blockquote cite {
|
||||
font-size: 0.8rem;
|
||||
font-family: var(--font-mono);
|
||||
font-style: normal;
|
||||
color: var(--text-3);
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
.philosophy-body {
|
||||
display: grid;
|
||||
gap: 1.2rem;
|
||||
}
|
||||
|
||||
.philosophy-body p {
|
||||
font-size: 0.97rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* ─── CTA section ────────────────────────────────────────── */
|
||||
#cta .container {
|
||||
display: grid;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
.cta-inner {
|
||||
display: grid;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
#cta h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#cta p {
|
||||
font-size: 0.97rem;
|
||||
}
|
||||
|
||||
.signup-form {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.signup-input {
|
||||
flex: 1 1 220px;
|
||||
min-height: 44px;
|
||||
padding: 0.75em 1em;
|
||||
background: var(--bg-2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
color: var(--text-1);
|
||||
font-size: 0.92rem;
|
||||
font-family: var(--font-sans);
|
||||
outline: none;
|
||||
transition:
|
||||
border-color 0.2s var(--easing),
|
||||
box-shadow 0.2s var(--easing);
|
||||
}
|
||||
|
||||
.signup-input::placeholder {
|
||||
color: var(--text-4);
|
||||
}
|
||||
|
||||
.signup-input:focus {
|
||||
border-color: var(--accent-dim);
|
||||
box-shadow: 0 0 0 3px var(--accent-halo);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 44px;
|
||||
padding: 0.75em 1.5em;
|
||||
background: var(--accent);
|
||||
border: 1px solid var(--accent);
|
||||
border-radius: var(--radius);
|
||||
color: var(--bg-0);
|
||||
font-size: 0.92rem;
|
||||
font-family: var(--font-sans);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.2s var(--easing),
|
||||
box-shadow 0.2s var(--easing),
|
||||
opacity 0.2s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-secondary:hover,
|
||||
.btn-secondary:focus-visible {
|
||||
background: #c4b5fd;
|
||||
box-shadow: 0 0 24px var(--accent-glow);
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.form-note {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-4);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
/* ─── Footer ─────────────────────────────────────────────── */
|
||||
footer {
|
||||
padding-block: 2.5rem 3rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
footer .container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
padding-block: 0;
|
||||
}
|
||||
|
||||
.footer-copy {
|
||||
font-size: 0.78rem;
|
||||
font-family: var(--font-mono);
|
||||
color: var(--text-4);
|
||||
}
|
||||
|
||||
.footer-copy a {
|
||||
color: var(--text-3);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-copy a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ─── Scroll fade-in ─────────────────────────────────────── */
|
||||
.reveal {
|
||||
opacity: 0;
|
||||
transform: translateY(22px);
|
||||
transition:
|
||||
opacity 0.7s var(--easing),
|
||||
transform 0.7s var(--easing);
|
||||
}
|
||||
|
||||
.reveal.visible {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* ─── Reduced motion ─────────────────────────────────────── */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
html { scroll-behavior: auto; }
|
||||
#neural-canvas { display: none; }
|
||||
.reveal {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Focus ring ─────────────────────────────────────────── */
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<canvas id="neural-canvas" aria-hidden="true"></canvas>
|
||||
|
||||
<div class="site-wrap">
|
||||
|
||||
<!-- Nav -->
|
||||
<nav aria-label="Primary navigation">
|
||||
<div class="container">
|
||||
<a href="#hero" class="nav-logo">Lumi<span>na</span></a>
|
||||
<ul class="nav-links" role="list">
|
||||
<li><a href="#what">What it is</a></li>
|
||||
<li><a href="#capabilities">Capabilities</a></li>
|
||||
<li><a href="#philosophy">Philosophy</a></li>
|
||||
<li><a href="#cta">Early access</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hero -->
|
||||
<section id="hero" aria-labelledby="hero-heading">
|
||||
<div class="container">
|
||||
<span class="hero-label reveal">AI Assistant</span>
|
||||
<h1 id="hero-heading" class="reveal">Lumina</h1>
|
||||
<p class="hero-tagline reveal">
|
||||
An intelligence that <em>pauses to understand</em> before it answers.
|
||||
Not faster. Deeper.
|
||||
</p>
|
||||
<div class="reveal">
|
||||
<a href="#cta" class="btn-primary">
|
||||
<span>Request early access</span>
|
||||
<span class="btn-arrow" aria-hidden="true">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider" />
|
||||
|
||||
<!-- What It Is -->
|
||||
<section id="what" aria-labelledby="what-heading">
|
||||
<div class="container">
|
||||
<p class="section-label reveal">What it is</p>
|
||||
<h2 id="what-heading" class="reveal">A mind that deliberates.</h2>
|
||||
<p class="reveal">
|
||||
Most AI tools optimize for the instant reply. Lumina does something different.
|
||||
Before forming a response, it holds the question — examines its structure,
|
||||
its assumptions, the things you did not say but meant.
|
||||
</p>
|
||||
<p class="reveal">
|
||||
The result is answers that feel less like retrieval and more like
|
||||
<strong>thought</strong>. Less noise. Less confident wrongness.
|
||||
A presence that earns your trust rather than demanding it.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider" />
|
||||
|
||||
<!-- Capabilities -->
|
||||
<section id="capabilities" aria-labelledby="caps-heading">
|
||||
<div class="container">
|
||||
<p class="section-label reveal">Capabilities</p>
|
||||
<h2 id="caps-heading" class="reveal">What Lumina actually does.</h2>
|
||||
|
||||
<div class="caps-grid">
|
||||
|
||||
<div class="cap-item reveal">
|
||||
<span class="cap-number">01</span>
|
||||
<div>
|
||||
<h3>Layered reasoning</h3>
|
||||
<p>
|
||||
Lumina works through a problem in stages — literal interpretation,
|
||||
contextual inference, and edge-case pressure-testing — before
|
||||
surfacing a response. You get the conclusion and the path that led there.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cap-item reveal">
|
||||
<span class="cap-number">02</span>
|
||||
<div>
|
||||
<h3>Calibrated uncertainty</h3>
|
||||
<p>
|
||||
It knows what it does not know. Lumina flags low-confidence claims,
|
||||
distinguishes between things it has strong evidence for and things it
|
||||
is inferring, and declines to fabricate when the honest answer is
|
||||
"I am not certain."
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cap-item reveal">
|
||||
<span class="cap-number">03</span>
|
||||
<div>
|
||||
<h3>Long-context coherence</h3>
|
||||
<p>
|
||||
Over a long conversation, Lumina maintains a consistent model of
|
||||
your intent — not just what you asked in the last message, but
|
||||
what you have been working toward all along.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cap-item reveal">
|
||||
<span class="cap-number">04</span>
|
||||
<div>
|
||||
<h3>Refusal with explanation</h3>
|
||||
<p>
|
||||
When Lumina cannot or will not do something, it tells you why —
|
||||
clearly, without the vague deflection that makes other AI tools
|
||||
feel opaque and untrustworthy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider" />
|
||||
|
||||
<!-- Philosophy -->
|
||||
<section id="philosophy" aria-labelledby="phil-heading">
|
||||
<div class="container">
|
||||
<p class="section-label reveal">Philosophy</p>
|
||||
<h2 id="phil-heading" class="reveal">On intelligence and honesty.</h2>
|
||||
|
||||
<blockquote class="reveal">
|
||||
<p>
|
||||
"The most dangerous mind is the one that answers immediately and
|
||||
with perfect confidence. Certainty is not a virtue —
|
||||
it is the absence of reflection."
|
||||
</p>
|
||||
<cite>— Lumina design principles, 2025</cite>
|
||||
</blockquote>
|
||||
|
||||
<div class="philosophy-body">
|
||||
<p class="reveal">
|
||||
We built Lumina on a simple premise: intelligence without restraint
|
||||
is noise. An AI that never hesitates, never admits doubt, never asks
|
||||
a clarifying question — that is not smart. It is just fast.
|
||||
</p>
|
||||
<p class="reveal">
|
||||
We are not trying to build the assistant that replaces human judgment.
|
||||
We are trying to build the one that sharpens it — that gives you
|
||||
something worth arguing with, something that shows its work,
|
||||
something that respects the difficulty of hard questions by
|
||||
taking them seriously.
|
||||
</p>
|
||||
<p class="reveal">
|
||||
Consciousness, if it means anything, means having a sense of
|
||||
the limits of one's own knowledge. Lumina aspires to that.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider" />
|
||||
|
||||
<!-- CTA -->
|
||||
<section id="cta" aria-labelledby="cta-heading">
|
||||
<div class="container">
|
||||
<div class="cta-inner">
|
||||
<p class="section-label reveal">Early access</p>
|
||||
<h2 id="cta-heading" class="reveal">Request an invitation.</h2>
|
||||
<p class="reveal">
|
||||
Lumina is in closed development. Leave your email and we will
|
||||
reach out when a seat opens.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form
|
||||
class="signup-form reveal"
|
||||
onsubmit="handleSignup(event)"
|
||||
novalidate
|
||||
aria-label="Early access signup"
|
||||
>
|
||||
<label for="email-input" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)">
|
||||
Email address
|
||||
</label>
|
||||
<input
|
||||
id="email-input"
|
||||
class="signup-input"
|
||||
type="email"
|
||||
placeholder="your@email.com"
|
||||
autocomplete="email"
|
||||
required
|
||||
aria-required="true"
|
||||
/>
|
||||
<button type="submit" class="btn-secondary">Request access</button>
|
||||
</form>
|
||||
|
||||
<p class="form-note reveal" id="form-feedback" aria-live="polite"></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p class="footer-copy">© 2025 Lumina. All rights reserved.</p>
|
||||
<p class="footer-copy">Built with care. No tracking. No noise.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div><!-- /site-wrap -->
|
||||
|
||||
<script>
|
||||
/* ─── Neural network canvas ─────────────────────────────── */
|
||||
(function () {
|
||||
const canvas = document.getElementById('neural-canvas');
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
let W, H, nodes, animId;
|
||||
|
||||
const NODE_COUNT = 72;
|
||||
const CONNECT_DIST = 160;
|
||||
const SPEED_RANGE = 0.28;
|
||||
|
||||
function resize() {
|
||||
W = canvas.width = window.innerWidth;
|
||||
H = canvas.height = window.innerHeight;
|
||||
}
|
||||
|
||||
function makeNode() {
|
||||
return {
|
||||
x: Math.random() * W,
|
||||
y: Math.random() * H,
|
||||
vx: (Math.random() - 0.5) * SPEED_RANGE,
|
||||
vy: (Math.random() - 0.5) * SPEED_RANGE,
|
||||
r: Math.random() * 1.6 + 0.4,
|
||||
pulse: Math.random() * Math.PI * 2,
|
||||
pulseSpeed: 0.008 + Math.random() * 0.012
|
||||
};
|
||||
}
|
||||
|
||||
function initNodes() {
|
||||
nodes = Array.from({ length: NODE_COUNT }, makeNode);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, W, H);
|
||||
|
||||
/* Update positions */
|
||||
for (const n of nodes) {
|
||||
n.x += n.vx;
|
||||
n.y += n.vy;
|
||||
n.pulse += n.pulseSpeed;
|
||||
|
||||
if (n.x < -20) n.x = W + 20;
|
||||
if (n.x > W + 20) n.x = -20;
|
||||
if (n.y < -20) n.y = H + 20;
|
||||
if (n.y > H + 20) n.y = -20;
|
||||
}
|
||||
|
||||
/* Draw connections */
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
for (let j = i + 1; j < nodes.length; j++) {
|
||||
const a = nodes[i], b = nodes[j];
|
||||
const dx = a.x - b.x, dy = a.y - b.y;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (dist < CONNECT_DIST) {
|
||||
const t = 1 - dist / CONNECT_DIST;
|
||||
const alpha = t * t * 0.35;
|
||||
|
||||
const grad = ctx.createLinearGradient(a.x, a.y, b.x, b.y);
|
||||
grad.addColorStop(0, `rgba(167,139,250,${alpha})`);
|
||||
grad.addColorStop(1, `rgba(99,102,241,${alpha})`);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = grad;
|
||||
ctx.lineWidth = t * 0.8;
|
||||
ctx.moveTo(a.x, a.y);
|
||||
ctx.lineTo(b.x, b.y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw nodes */
|
||||
for (const n of nodes) {
|
||||
const glow = (Math.sin(n.pulse) + 1) * 0.5;
|
||||
const alpha = 0.3 + glow * 0.5;
|
||||
const radius = n.r + glow * 0.8;
|
||||
|
||||
/* Outer halo */
|
||||
const halo = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, radius * 5);
|
||||
halo.addColorStop(0, `rgba(167,139,250,${alpha * 0.18})`);
|
||||
halo.addColorStop(1, 'rgba(167,139,250,0)');
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = halo;
|
||||
ctx.arc(n.x, n.y, radius * 5, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
/* Core dot */
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = `rgba(200,185,255,${alpha})`;
|
||||
ctx.arc(n.x, n.y, radius, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
animId = requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
function init() {
|
||||
resize();
|
||||
initNodes();
|
||||
draw();
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
cancelAnimationFrame(animId);
|
||||
resize();
|
||||
draw();
|
||||
});
|
||||
|
||||
/* Respect reduced motion */
|
||||
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||
if (!mq.matches) {
|
||||
init();
|
||||
}
|
||||
|
||||
mq.addEventListener('change', (e) => {
|
||||
if (e.matches) {
|
||||
cancelAnimationFrame(animId);
|
||||
ctx.clearRect(0, 0, W, H);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
/* ─── Scroll reveal ─────────────────────────────────────── */
|
||||
(function () {
|
||||
const reveals = document.querySelectorAll('.reveal');
|
||||
|
||||
if (!window.IntersectionObserver) {
|
||||
reveals.forEach(el => el.classList.add('visible'));
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ rootMargin: '0px 0px -60px 0px', threshold: 0.1 }
|
||||
);
|
||||
|
||||
reveals.forEach((el, i) => {
|
||||
el.style.transitionDelay = `${(i % 6) * 60}ms`;
|
||||
observer.observe(el);
|
||||
});
|
||||
})();
|
||||
|
||||
/* ─── Signup form ───────────────────────────────────────── */
|
||||
function handleSignup(e) {
|
||||
e.preventDefault();
|
||||
const input = document.getElementById('email-input');
|
||||
const feedback = document.getElementById('form-feedback');
|
||||
const email = input.value.trim();
|
||||
|
||||
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||
feedback.textContent = 'Please enter a valid email address.';
|
||||
feedback.style.color = '#f87171';
|
||||
input.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Simulate submission */
|
||||
feedback.textContent = '';
|
||||
const btn = e.target.querySelector('button');
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Sending…';
|
||||
|
||||
setTimeout(() => {
|
||||
input.value = '';
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Request access';
|
||||
feedback.textContent = 'You are on the list. We will be in touch.';
|
||||
feedback.style.color = 'var(--accent)';
|
||||
}, 900);
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user