diff --git a/website/src/components/landing/ClosingSection.astro b/website/src/components/landing/ClosingSection.astro new file mode 100644 index 00000000..dea0c78b --- /dev/null +++ b/website/src/components/landing/ClosingSection.astro @@ -0,0 +1,20 @@ +
+

04 / RUN IT

+
+

Protect the graph,
not just the names.

+
+

The CLI currently registers the JVM stack and runs it from a YAML configuration. Start at the source, then tune each transform around the application’s real ABI.

+
+ neko obfuscate -c config.yml + +
+ + github.com/Fadouse/neko-obfuscator + + +
+
+
diff --git a/website/src/components/landing/LandingFooter.astro b/website/src/components/landing/LandingFooter.astro new file mode 100644 index 00000000..31a0dc8d --- /dev/null +++ b/website/src/components/landing/LandingFooter.astro @@ -0,0 +1,5 @@ + diff --git a/website/src/components/landing/LandingHero.astro b/website/src/components/landing/LandingHero.astro new file mode 100644 index 00000000..411dadf2 --- /dev/null +++ b/website/src/components/landing/LandingHero.astro @@ -0,0 +1,114 @@ +
+
+
+ OPEN SOURCE + + JVM + NATIVE PROTECTION +
+ +

+ Destroy the + static shape + of Java. +

+ +

+ NekoObfuscator composes dependency-aware bytecode transforms, binds protected data to live control flow, and can translate selected methods into native libraries. +

+ + + +
+
+ 09 + registered JVM passes +
+
+ 05 + native build targets +
+
+ C11 + generated through Zig CC +
+
+
+ + +
+ + diff --git a/website/src/components/landing/LandingNav.astro b/website/src/components/landing/LandingNav.astro new file mode 100644 index 00000000..a8325d5b --- /dev/null +++ b/website/src/components/landing/LandingNav.astro @@ -0,0 +1,24 @@ + diff --git a/website/src/components/landing/NativeSection.astro b/website/src/components/landing/NativeSection.astro new file mode 100644 index 00000000..fa50501a --- /dev/null +++ b/website/src/components/landing/NativeSection.astro @@ -0,0 +1,72 @@ +--- +const targets = [ + 'linux / x86_64', + 'linux / aarch64', + 'windows / x86_64', + 'macOS / x86_64', + 'macOS / aarch64', +]; +--- + +
+
+
+ 03 / SELECTIVE NATIVE BACKEND + BYTECODE → C → SHARED LIBRARY +
+ +
+

Move selected methods
outside the class file.

+

+ Candidate methods pass a safety checker, translate into generated C, compile through Zig for configured targets, and return to the JAR as platform libraries with runtime loading and binding support. +

+
+ +
+ +
+ 01 + SELECT + annotations + filters +
+
+ 02 + VERIFY + safety closure +
+
+ 03 + TRANSLATE + L1 bytecode → C IR +
+
+ 04 + COMPILE + Zig CC / C11 / O3 +
+
+ 05 + LOAD + JAR resource → runtime +
+
+ +
+
+

EMITTED TARGETS

+
+ {targets.map((target) => {target})} +
+
+ +
+
native-stage.log
+

safety-check selected methods

+

generate sliced C source set

+

zig cc -O3 -shared -target …

+

pack /neko/native/libneko_*

+

runtime loader installed

+
+
+
+
diff --git a/website/src/components/landing/PipelineSection.astro b/website/src/components/landing/PipelineSection.astro new file mode 100644 index 00000000..7a3e6816 --- /dev/null +++ b/website/src/components/landing/PipelineSection.astro @@ -0,0 +1,44 @@ +--- +const stages = [ + { id: 'renamer', name: 'Renamer', phase: 'PRE', detail: 'Class/member remap, reflective literals, manifest entry, debug metadata, mapping output.' }, + { id: 'keyDispatch', name: 'Key dispatch', phase: 'PRE', detail: 'Hidden long-key propagation for mutable descriptors; local key seeding for fixed JVM entry points.' }, + { id: 'methodParameterObfuscation', name: 'Parameter carriers', phase: 'PRE', detail: 'Eligible arguments become a single Object[] carrier with rewritten direct, reflective, lambda, and proxy paths.' }, + { id: 'controlFlowFlattening', name: 'Control-flow flattening', phase: 'CORE', detail: 'Original method body becomes keyed verifier-safe blocks routed through target-local dispatchers.' }, + { id: 'validationSinkHardening', name: 'Validation sinks', phase: 'CORE', detail: 'Compact validation patterns become staged checks coupled to live CFF state.' }, + { id: 'runtimeVariableObfuscation', name: 'Runtime variables', phase: 'CORE', detail: 'Primitive locals move into encrypted shadow slots with masks recomputed from the running flow.' }, + { id: 'invokeDynamic', name: 'InvokeDynamic references', phase: 'CORE', detail: 'Field and method references become flow-keyed indy sites with encrypted bootstrap material.' }, + { id: 'constantObfuscation', name: 'Numeric constants', phase: 'CORE', detail: 'Pushes, LDC values, arrays, and ConstantValue material are decoded against live CFF keys.' }, + { id: 'stringObfuscation', name: 'String protection', phase: 'CORE', detail: 'Literal and concat constants are encrypted per site, decoded with flow state, and cached where useful.' }, +]; +--- + +
+
+
+

02 / ACTUAL PASS ORDER

+

Nine stages.
One dependency graph.

+

These are the passes registered by the CLI today, in the order exposed by the codebase.

+
+ PRE_TRANSFORM + TRANSFORM +
+
+ +
+ {stages.map((stage, index) => ( +
+
{String(index + 1).padStart(2, '0')}
+
+
+

{stage.name}

+ {stage.phase} +
+

{stage.detail}

+ {stage.id} +
+ +
+ ))} +
+
+
diff --git a/website/src/components/landing/ProtectionSystem.astro b/website/src/components/landing/ProtectionSystem.astro new file mode 100644 index 00000000..0b8a929c --- /dev/null +++ b/website/src/components/landing/ProtectionSystem.astro @@ -0,0 +1,60 @@ +--- +const protectionLayers = [ + { + index: '01', + eyebrow: 'IDENTITY', + title: 'Erase the readable surface.', + description: 'Deterministic class and member renaming rewrites references, manifests, reflective strings, enum annotation values, and mapping output as one coordinated pass.', + signal: 'renamer', + }, + { + index: '02', + eyebrow: 'EXECUTION', + title: 'Make control flow carry the key.', + description: 'Eligible methods receive hidden key material; verifier-safe blocks return through local dispatchers with encoded, evolving state instead of a readable graph.', + signal: 'keyDispatch → CFF', + }, + { + index: '03', + eyebrow: 'DATA', + title: 'Bind values to live flow.', + description: 'Primitive locals, numeric constants, strings, validation sites, and dynamic references derive material from the active control-flow state—not a detached global secret.', + signal: 'flow-keyed material', + }, + { + index: '04', + eyebrow: 'CALL SURFACE', + title: 'Break familiar method shapes.', + description: 'Eligible parameter lists collapse into Object[] carriers while call sites, constructors, lambdas, proxies, method handles, and reflective lookups are reconciled around the new ABI.', + signal: 'carrier ABI', + }, +]; +--- + +
+
+

01 / PROTECTION SYSTEM

+

Not a bag of tricks.
A shared runtime state.

+

The strongest parts of the current implementation are connected: later transforms consume metadata and keys produced by earlier passes.

+
+ +
+ {protectionLayers.map((layer) => ( +
+
+ {layer.index} + {layer.eyebrow} +
+ +

{layer.title}

+

{layer.description}

+
+ {layer.signal} + +
+
+ ))} +
+
diff --git a/website/src/layouts/BaseLayout.astro b/website/src/layouts/BaseLayout.astro index 9b613d86..28b46ad5 100644 --- a/website/src/layouts/BaseLayout.astro +++ b/website/src/layouts/BaseLayout.astro @@ -1,5 +1,15 @@ --- import '../styles/global.css'; + +interface Props { + title?: string; + description?: string; +} + +const { + title = 'NekoObfuscator — Layered JVM & Native Protection', + description = 'A code-driven Java protection toolchain with dependency-aware JVM transforms, flow-keyed data protection, and selective native translation.', +} = Astro.props; --- @@ -7,234 +17,17 @@ import '../styles/global.css'; - - NekoObfuscator + + + + + + + {title} - - - - + - - -
- -
- - + - - diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index 1340fba9..23370bed 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -1,18 +1,202 @@ --- import BaseLayout from '../layouts/BaseLayout.astro'; -import HeroSection from '../components/HeroSection.astro'; -import FeaturesSection from '../components/FeaturesSection.astro'; -import NativeSection from '../components/NativeSection.astro'; -import AINativeSection from '../components/AINativeSection.astro'; -import PerformanceSection from '../components/PerformanceSection.astro'; -import FooterSection from '../components/FooterSection.astro'; +import LandingNav from '../components/landing/LandingNav.astro'; +import LandingHero from '../components/landing/LandingHero.astro'; +import ProtectionSystem from '../components/landing/ProtectionSystem.astro'; +import PipelineSection from '../components/landing/PipelineSection.astro'; +import NativeSection from '../components/landing/NativeSection.astro'; +import ClosingSection from '../components/landing/ClosingSection.astro'; +import LandingFooter from '../components/landing/LandingFooter.astro'; +import '../styles/landing-shell.css'; +import '../styles/landing-system.css'; +import '../styles/landing-native.css'; +import '../styles/landing-responsive.css'; --- - - - - - - +
+ + + + + +
+ + + + + +
+ + +
+ + diff --git a/website/src/styles/global.css b/website/src/styles/global.css index 4686e68a..fb0aef61 100644 --- a/website/src/styles/global.css +++ b/website/src/styles/global.css @@ -1,4 +1,3 @@ -/* ── Fonts ── */ @import '@fontsource/inter/latin-400.css'; @import '@fontsource/inter/latin-500.css'; @import '@fontsource/inter/latin-600.css'; @@ -6,144 +5,140 @@ @import '@fontsource/jetbrains-mono/latin-400.css'; @import '@fontsource/jetbrains-mono/latin-500.css'; -/* ── Theme tokens ── */ :root { - /* Cold gray + steel blue palette — light */ - --bg-primary: #f2f3f5; - --bg-secondary: #e8eaed; - --bg-card: rgba(255, 255, 255, 0.72); - --bg-card-hover: rgba(255, 255, 255, 0.88); - --bg-glass: rgba(255, 255, 255, 0.48); - --text-primary: #1a1c1e; - --text-secondary: #5f6368; - --text-tertiary: #8a8f94; - --accent: #5b7a9a; - --accent-subtle: rgba(91, 122, 154, 0.12); - --accent-glow: rgba(91, 122, 154, 0.24); - --border: rgba(0, 0, 0, 0.08); - --border-strong: rgba(0, 0, 0, 0.12); - --divider: rgba(0, 0, 0, 0.06); - - /* Layout */ - --max-width: 1200px; - --nav-height: 56px; - - /* Typography */ + --bg: #070908; + --bg-raised: #0c0f0d; + --bg-soft: #111512; + --text: #f1f5ef; + --text-muted: #9aa39b; + --text-dim: #667068; + --line: rgba(236, 244, 236, 0.12); + --line-strong: rgba(236, 244, 236, 0.22); + --lime: #a7ff75; + --lime-soft: rgba(167, 255, 117, 0.13); + --ice: #9fc8ff; + --max-width: 1240px; --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; - --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace; - - /* Easing */ - --ease-spring: cubic-bezier(0.25, 0.1, 0.25, 1); - --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); - --ease-in-out-expo: cubic-bezier(0.87, 0, 0.13, 1); -} - -/* ── Dark theme ── */ -[data-theme='dark'] { - --bg-primary: #1a1c1e; - --bg-secondary: #202326; - --bg-card: rgba(40, 44, 48, 0.72); - --bg-card-hover: rgba(40, 44, 48, 0.88); - --bg-glass: rgba(40, 44, 48, 0.48); - --text-primary: #e8eaed; - --text-secondary: #9aa0a6; - --text-tertiary: #6b7280; - --accent: #7ba4c2; - --accent-subtle: rgba(123, 164, 194, 0.12); - --accent-glow: rgba(123, 164, 194, 0.18); - --border: rgba(255, 255, 255, 0.08); - --border-strong: rgba(255, 255, 255, 0.12); - --divider: rgba(255, 255, 255, 0.06); -} - -/* ── Reset & base ── */ + --font-mono: 'JetBrains Mono', 'SFMono-Regular', Consolas, monospace; + --ease-out: cubic-bezier(0.16, 1, 0.3, 1); +} + *, *::before, *::after { + box-sizing: border-box; margin: 0; padding: 0; - box-sizing: border-box; } html { + color-scheme: dark; scroll-behavior: smooth; + background: var(--bg); -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; } body { - font-family: var(--font-sans); - background: var(--bg-primary); - color: var(--text-primary); - line-height: 1.6; + min-width: 320px; + min-height: 100vh; overflow-x: hidden; + font-family: var(--font-sans); + color: var(--text); + background: + radial-gradient(circle at 16% -10%, rgba(167, 255, 117, 0.075), transparent 32rem), + radial-gradient(circle at 92% 28%, rgba(159, 200, 255, 0.055), transparent 30rem), + var(--bg); } -/* Theme transitions only after page is ready — prevents flash on load */ -.theme-ready body { - transition: background-color 0.4s var(--ease-spring), color 0.4s var(--ease-spring); +body::before { + position: fixed; + inset: 0; + z-index: 1000; + pointer-events: none; + content: ''; + opacity: 0.035; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.9'/%3E%3C/svg%3E"); } -.theme-ready .nav-bar { - transition: background 0.4s var(--ease-spring), border-color 0.4s var(--ease-spring); +button, +a { + -webkit-tap-highlight-color: transparent; } -.theme-ready .native-section { - transition: background 0.4s var(--ease-spring); +a { + color: inherit; + text-decoration: none; +} + +button { + color: inherit; + font: inherit; } -/* ── Typography ── */ -h1, h2, h3, h4 { - font-weight: 600; - letter-spacing: -0.02em; +img, +svg { + display: block; + max-width: 100%; } -p { - color: var(--text-secondary); +::selection { + color: #081006; + background: var(--lime); } -code, pre { +.container { + width: min(calc(100% - 48px), var(--max-width)); + margin-inline: auto; +} + +.mono { font-family: var(--font-mono); } -a { - color: var(--accent); - text-decoration: none; - transition: opacity 0.2s ease; +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } -a:hover { - opacity: 0.8; +::-webkit-scrollbar { + width: 10px; } -/* ── Utility ── */ -.container { - width: 100%; - max-width: var(--max-width); - margin: 0 auto; - padding: 0 24px; -} - -.section-label { - font-size: 0.75rem; - font-weight: 600; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--accent); - margin-bottom: 12px; -} - -.section-title { - font-size: clamp(2rem, 4vw, 3.2rem); - font-weight: 700; - letter-spacing: -0.03em; - line-height: 1.15; - margin-bottom: 16px; -} - -.section-subtitle { - font-size: 1.1rem; - color: var(--text-secondary); - max-width: 560px; - line-height: 1.6; +::-webkit-scrollbar-track { + background: var(--bg); +} + +::-webkit-scrollbar-thumb { + border: 3px solid var(--bg); + border-radius: 999px; + background: #293029; +} + +@media (max-width: 720px) { + .container { + width: min(calc(100% - 32px), var(--max-width)); + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + scroll-behavior: auto !important; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } } diff --git a/website/src/styles/landing-native.css b/website/src/styles/landing-native.css new file mode 100644 index 00000000..dd4ab68d --- /dev/null +++ b/website/src/styles/landing-native.css @@ -0,0 +1,288 @@ +.native-section { + padding-top: 0; +} + +.native-panel { + position: relative; + overflow: hidden; + padding: clamp(28px, 5vw, 72px); + border: 1px solid var(--line-strong); + border-radius: 28px; + background: + radial-gradient(circle at 86% 14%, rgba(159, 200, 255, 0.1), transparent 26rem), + radial-gradient(circle at 10% 90%, rgba(167, 255, 117, 0.08), transparent 30rem), + var(--bg-raised); +} + +.native-panel::before { + position: absolute; + inset: 0; + pointer-events: none; + content: ''; + background-image: + linear-gradient(rgba(255, 255, 255, 0.032) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.032) 1px, transparent 1px); + background-size: 44px 44px; + mask-image: radial-gradient(circle at center, black, transparent 78%); +} + +.native-topline { + position: relative; + display: flex; + justify-content: space-between; + padding-bottom: 20px; + color: var(--text-dim); + border-bottom: 1px solid var(--line); + font-size: 0.58rem; + letter-spacing: 0.1em; +} + +.native-copy { + position: relative; + display: grid; + grid-template-columns: 1.2fr 0.8fr; + gap: 72px; + align-items: end; + padding-top: 66px; +} + +.native-copy > p { + max-width: 520px; + padding-bottom: 8px; +} + +.native-route { + position: relative; + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: 18px; + margin-top: 88px; +} + +.native-route-line { + position: absolute; + top: 19px; + left: 20px; + right: 20px; + height: 1px; + transform: scaleX(0); + transform-origin: left; + background: linear-gradient(90deg, var(--lime), var(--ice)); +} + +.native-node { + position: relative; + display: flex; + flex-direction: column; + gap: 8px; + padding-top: 46px; +} + +.native-node::before { + position: absolute; + top: 12px; + left: 12px; + z-index: 2; + width: 14px; + aspect-ratio: 1; + border: 4px solid var(--bg-raised); + border-radius: 50%; + content: ''; + background: var(--lime); + box-shadow: 0 0 18px rgba(167, 255, 117, 0.35); +} + +.native-node:nth-of-type(even)::before { + background: var(--ice); + box-shadow: 0 0 18px rgba(159, 200, 255, 0.35); +} + +.native-node-index { + color: var(--text-dim); + font-size: 0.55rem; +} + +.native-node strong { + font-family: var(--font-mono); + font-size: 0.72rem; + font-weight: 500; + letter-spacing: 0.08em; +} + +.native-node small { + color: var(--text-dim); + font-size: 0.7rem; +} + +.native-bottom { + position: relative; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 28px; + margin-top: 80px; +} + +.target-block, +.native-terminal { + min-height: 240px; + padding: 24px; + border: 1px solid var(--line); + border-radius: 16px; + background: rgba(0, 0, 0, 0.18); +} + +.target-label { + color: var(--text-dim); + font-size: 0.58rem; + letter-spacing: 0.1em; +} + +.target-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px; + margin-top: 28px; +} + +.target-grid span { + padding: 13px 14px; + color: #cbd2cc; + border: 1px solid var(--line); + border-radius: 9px; + background: rgba(255, 255, 255, 0.025); + font-size: 0.61rem; +} + +.target-grid span:last-child { + grid-column: 1 / -1; +} + +.native-terminal { + color: #b9c0ba; + font-size: 0.65rem; + line-height: 2.1; +} + +.native-terminal p i { + display: inline-block; + width: 18px; + color: var(--text-dim); + font-style: normal; +} + +.native-terminal .terminal-ok { + margin-top: 8px; + color: var(--lime); +} + +.closing { + padding-bottom: clamp(120px, 12vw, 180px); +} + +.closing-grid { + display: grid; + grid-template-columns: 1.2fr 0.8fr; + gap: clamp(60px, 10vw, 150px); + align-items: start; + margin-top: 34px; +} + +.closing-side { + padding-top: 8px; +} + +.command-bar { + display: grid; + grid-template-columns: 1fr auto; + align-items: center; + min-height: 62px; + padding-left: 18px; + margin-top: 32px; + border: 1px solid var(--line); + border-radius: 12px; + background: rgba(255, 255, 255, 0.025); +} + +.command-bar code { + overflow: hidden; + color: #dce2dc; + font-size: 0.7rem; + text-overflow: ellipsis; + white-space: nowrap; +} + +.command-bar button { + position: relative; + min-width: 84px; + align-self: stretch; + border: 0; + border-left: 1px solid var(--line); + background: transparent; + cursor: pointer; + font-size: 0.58rem; + letter-spacing: 0.08em; +} + +.copy-success { + position: absolute; + inset: 0; + display: grid; + color: var(--lime); + opacity: 0; + place-items: center; +} + +.command-bar button[data-copied='true'] .copy-default { + opacity: 0; +} + +.command-bar button[data-copied='true'] .copy-success { + opacity: 1; +} + +.text-link { + display: inline-flex; + align-items: center; + gap: 10px; + margin-top: 25px; + color: var(--lime); + font-size: 0.78rem; +} + +.text-link svg { + width: 18px; + transition: transform 0.3s var(--ease-out); +} + +.text-link:hover svg { + transform: translate(3px, -3px); +} + +.site-footer { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + min-height: 84px; + color: var(--text-dim); + border-top: 1px solid var(--line); + font-size: 0.56rem; + letter-spacing: 0.09em; +} + +.site-footer span:nth-child(2) { + text-align: center; +} + +.site-footer a { + justify-self: end; + color: var(--text-muted); +} + +@keyframes machine-scan { + 0%, 28% { transform: translateX(-120%); } + 65%, 100% { transform: translateX(120%); } +} + +@keyframes tape { + to { transform: translateX(-50%); } +} diff --git a/website/src/styles/landing-responsive.css b/website/src/styles/landing-responsive.css new file mode 100644 index 00000000..bcc095e0 --- /dev/null +++ b/website/src/styles/landing-responsive.css @@ -0,0 +1,275 @@ +@media (max-width: 1080px) { + .hero { + grid-template-columns: 1fr; + padding-top: 170px; + } + + .hero-copy-block { + max-width: 860px; + } + + .hero-visual-wrap { + width: min(100%, 650px); + margin: 28px auto 0; + } + + .section-heading { + grid-template-columns: 0.5fr 1.5fr; + } + + .section-heading > p:last-child { + grid-column: 2; + } + + .pipeline-layout { + grid-template-columns: 0.72fr 1.28fr; + gap: 70px; + } + + .native-copy { + grid-template-columns: 1fr; + gap: 28px; + } +} + +@media (max-width: 820px) { + .site-nav { + grid-template-columns: 1fr auto; + } + + .nav-links { + display: none; + } + + .hero-title { + font-size: clamp(3.6rem, 13vw, 6rem); + } + + .section-heading, + .pipeline-layout, + .closing-grid { + grid-template-columns: 1fr; + } + + .section-heading > p:last-child { + grid-column: auto; + max-width: 590px; + } + + .pipeline-sticky { + position: relative; + top: auto; + margin-bottom: 28px; + } + + .layer-grid { + grid-template-columns: 1fr; + } + + .native-route { + grid-template-columns: 1fr; + gap: 4px; + } + + .native-route-line { + top: 20px; + bottom: 20px; + left: 18px; + right: auto; + width: 1px; + height: auto; + transform: scaleY(0); + transform-origin: top; + background: linear-gradient(var(--lime), var(--ice)); + } + + .native-node { + min-height: 92px; + padding: 10px 0 10px 58px; + } + + .native-node::before { + top: 18px; + left: 11px; + } + + .native-bottom { + grid-template-columns: 1fr; + } + + .site-footer { + grid-template-columns: 1fr auto; + } + + .site-footer span:nth-child(2) { + display: none; + } +} + +@media (max-width: 600px) { + .machine-orbit { + display: none; + } + + .site-nav { + top: 10px; + min-height: 50px; + border-radius: 13px; + } + + .nav-github span { + display: none; + } + + .nav-github { + width: 38px; + height: 38px; + padding: 0; + } + + .hero { + min-height: auto; + padding-top: 142px; + padding-bottom: 72px; + } + + .hero-kicker { + flex-wrap: wrap; + margin-bottom: 22px; + } + + .hero-lede { + margin-top: 24px; + } + + .hero-stats { + grid-template-columns: 1fr; + gap: 14px; + margin-top: 42px; + } + + .hero-stat { + display: grid; + grid-template-columns: 70px 1fr; + align-items: center; + } + + .hero-machine { + min-height: 520px; + border-radius: 18px; + } + + .machine-body { + min-height: 420px; + padding: 13px; + } + + .machine-core-wrap { + min-height: 200px; + } + + .machine-core { + width: 195px; + } + + .machine-chrome > span:nth-child(2), + .machine-footer > span:last-child { + display: none; + } + + .system-section, + .pipeline-section, + .closing { + padding-top: 110px; + } + + .section-heading h2, + .pipeline-sticky h2, + .native-copy h2, + .closing h2 { + font-size: clamp(2.5rem, 13vw, 4.1rem); + } + + .layer-grid { + margin-top: 55px; + border-radius: 16px; + } + + .layer-card { + min-height: auto; + padding: 22px; + } + + .layer-card-icon { + margin: 38px 0 32px; + } + + .stage { + grid-template-columns: 38px 1fr 25px; + gap: 12px; + } + + .stage-title-row { + align-items: flex-start; + } + + .stage-phase { + margin-top: 3px; + } + + .stage-list::before { + right: 12px; + } + + .stage-node { + width: 25px; + height: 25px; + } + + .native-panel { + padding: 22px; + border-radius: 19px; + } + + .native-topline span:last-child { + display: none; + } + + .native-copy { + padding-top: 45px; + } + + .native-route, + .native-bottom { + margin-top: 58px; + } + + .target-grid { + grid-template-columns: 1fr; + } + + .target-grid span:last-child { + grid-column: auto; + } + + .command-bar { + grid-template-columns: minmax(0, 1fr) 74px; + padding-left: 13px; + } + + .command-bar code { + font-size: 0.61rem; + } +} + +@media (prefers-reduced-motion: reduce) { + .hero-machine::before, + .signal-tape-track { + animation: none; + } + + .cursor-glow, + .machine-orbit { + display: none; + } +} diff --git a/website/src/styles/landing-shell.css b/website/src/styles/landing-shell.css new file mode 100644 index 00000000..49c213d2 --- /dev/null +++ b/website/src/styles/landing-shell.css @@ -0,0 +1,557 @@ +.page { + position: relative; + overflow-x: clip; + isolation: isolate; +} + +.page::before { + position: absolute; + inset: 0; + z-index: -2; + pointer-events: none; + content: ''; + background-image: + linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px); + background-size: 72px 72px; + mask-image: linear-gradient(to bottom, black, transparent 28%, transparent 82%, black); +} + +.cursor-glow { + position: fixed; + top: 0; + left: 0; + z-index: -1; + width: 36rem; + aspect-ratio: 1; + pointer-events: none; + opacity: 0; + border-radius: 50%; + background: radial-gradient(circle, rgba(167, 255, 117, 0.055), transparent 68%); + will-change: transform; +} + +.scroll-meter { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 300; + height: 2px; +} + +.scroll-meter__bar { + display: block; + width: 100%; + height: 100%; + transform: scaleX(0); + transform-origin: left; + background: linear-gradient(90deg, var(--lime), var(--ice)); +} + +.site-nav { + position: fixed; + top: 18px; + left: 50%; + z-index: 200; + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + min-height: 54px; + padding: 8px 10px 8px 16px; + border: 1px solid var(--line); + border-radius: 16px; + background: rgba(8, 10, 9, 0.72); + box-shadow: 0 18px 60px rgba(0, 0, 0, 0.26); + backdrop-filter: blur(18px) saturate(130%); + transform: translateX(-50%); +} + +.brand { + display: inline-flex; + align-items: center; + gap: 10px; + width: fit-content; + font-family: var(--font-mono); + font-size: 0.76rem; + font-weight: 500; + letter-spacing: 0.08em; +} + +.brand-mark { + display: grid; + width: 30px; + aspect-ratio: 1; + place-items: center; + color: var(--lime); + border: 1px solid var(--line); + border-radius: 9px; + background: var(--lime-soft); +} + +.brand-mark svg { + width: 20px; +} + +.brand-dim { + color: var(--text-dim); +} + +.nav-links { + display: flex; + align-items: center; + gap: 4px; + padding: 4px; + border: 1px solid rgba(255, 255, 255, 0.055); + border-radius: 11px; + background: rgba(255, 255, 255, 0.025); +} + +.nav-links a { + padding: 7px 13px; + color: var(--text-muted); + border-radius: 8px; + font-size: 0.76rem; + transition: color 0.25s ease, background 0.25s ease; +} + +.nav-links a:hover { + color: var(--text); + background: rgba(255, 255, 255, 0.06); +} + +.nav-github { + display: inline-flex; + align-items: center; + justify-self: end; + gap: 9px; + padding: 10px 13px; + color: #071006; + border-radius: 10px; + background: var(--lime); + font-size: 0.76rem; + font-weight: 600; + transition: transform 0.25s var(--ease-out), box-shadow 0.25s ease; +} + +.nav-github:hover { + transform: translateY(-1px); + box-shadow: 0 10px 32px rgba(167, 255, 117, 0.16); +} + +.nav-github svg { + width: 16px; +} + +.hero { + display: grid; + grid-template-columns: minmax(0, 1.02fr) minmax(420px, 0.98fr); + align-items: center; + gap: clamp(36px, 6vw, 100px); + min-height: 100svh; + padding-top: 140px; + padding-bottom: 80px; +} + +.hero-copy-block { + position: relative; + z-index: 2; +} + +.hero-kicker { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 30px; + color: var(--text-muted); + font-size: 0.67rem; + letter-spacing: 0.12em; +} + +.hero-kicker-dot { + width: 5px; + aspect-ratio: 1; + border-radius: 50%; + background: var(--lime); + box-shadow: 0 0 14px var(--lime); +} + +.hero-title { + max-width: 760px; + font-size: clamp(4rem, 7.2vw, 7rem); + font-weight: 600; + letter-spacing: -0.075em; + line-height: 0.9; +} + +.hero-title .line { + display: block; + overflow: hidden; + padding-right: 0.08em; + padding-bottom: 0.08em; +} + +.hero-title .line > span { + display: inline-block; + will-change: transform; +} + +.outline-word { + color: transparent; + -webkit-text-stroke: 1px rgba(241, 245, 239, 0.6); + text-stroke: 1px rgba(241, 245, 239, 0.6); +} + +.hero-lede { + max-width: 610px; + margin-top: 30px; + color: var(--text-muted); + font-size: clamp(1rem, 1.35vw, 1.14rem); + line-height: 1.75; +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 34px; +} + +.button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 10px; + min-height: 50px; + padding: 0 20px; + border: 1px solid transparent; + border-radius: 12px; + font-size: 0.84rem; + font-weight: 600; + will-change: transform; +} + +.button svg { + width: 18px; +} + +.button-primary { + color: #071006; + background: var(--lime); +} + +.button-quiet { + color: var(--text); + border-color: var(--line); + background: rgba(255, 255, 255, 0.035); + backdrop-filter: blur(12px); +} + +.hero-stats { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 22px; + max-width: 650px; + margin-top: 56px; + padding-top: 22px; + border-top: 1px solid var(--line); +} + +.hero-stat { + display: flex; + flex-direction: column; + gap: 6px; +} + +.hero-stat strong { + color: var(--text); + font-size: 1rem; + font-weight: 500; +} + +.hero-stat span { + color: var(--text-dim); + font-size: 0.72rem; + line-height: 1.45; +} + +.hero-visual-wrap { + position: relative; + perspective: 1200px; +} + +.machine-orbit { + position: absolute; + top: 50%; + left: 50%; + z-index: -1; + border: 1px solid rgba(167, 255, 117, 0.12); + border-radius: 50%; + transform: translate(-50%, -50%); +} + +.machine-orbit::before, +.machine-orbit::after { + position: absolute; + aspect-ratio: 1; + border-radius: 50%; + content: ''; + background: var(--lime); + box-shadow: 0 0 18px rgba(167, 255, 117, 0.45); +} + +.orbit-one { + width: 118%; + aspect-ratio: 1; + border-style: dashed; +} + +.orbit-one::before { + top: 8%; + left: 20%; + width: 5px; +} + +.orbit-one::after { + right: 8%; + bottom: 28%; + width: 3px; + background: var(--ice); +} + +.orbit-two { + width: 92%; + aspect-ratio: 1; + border-color: rgba(159, 200, 255, 0.1); +} + +.orbit-two::before { + top: 50%; + left: -3px; + width: 4px; + background: var(--ice); +} + +.orbit-two::after { + right: 21%; + bottom: 4%; + width: 4px; +} + +.hero-machine { + position: relative; + overflow: hidden; + min-height: 560px; + border: 1px solid var(--line-strong); + border-radius: 24px; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.06), transparent 30%), + rgba(10, 13, 11, 0.88); + box-shadow: 0 40px 100px rgba(0, 0, 0, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.06); + backdrop-filter: blur(20px); + transform-style: preserve-3d; + will-change: transform; +} + +.hero-machine::before { + position: absolute; + inset: 0; + pointer-events: none; + content: ''; + background: linear-gradient(115deg, transparent 25%, rgba(167, 255, 117, 0.045) 48%, transparent 70%); + transform: translateX(-100%); + animation: machine-scan 7s ease-in-out infinite; +} + +.machine-chrome, +.machine-footer { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 48px; + padding: 0 18px; + color: var(--text-dim); + font-size: 0.58rem; + letter-spacing: 0.1em; +} + +.machine-chrome { + border-bottom: 1px solid var(--line); +} + +.chrome-dots { + display: inline-flex; + gap: 5px; +} + +.chrome-dots i { + width: 6px; + aspect-ratio: 1; + border-radius: 50%; + background: #333a34; +} + +.chrome-dots i:first-child { + background: var(--lime); +} + +.machine-body { + display: grid; + grid-template-rows: auto 1fr auto; + min-height: 462px; + padding: 20px; +} + +.machine-code { + position: relative; + z-index: 2; + padding: 16px; + border: 1px solid var(--line); + border-radius: 12px; + background: rgba(0, 0, 0, 0.22); + font-size: 0.66rem; + line-height: 1.8; +} + +.code-head, +.output-head, +.terminal-head { + display: flex; + justify-content: space-between; + padding-bottom: 10px; + margin-bottom: 10px; + color: var(--text-dim); + border-bottom: 1px solid var(--line); + font-size: 0.57rem; + letter-spacing: 0.08em; +} + +.machine-code p { + color: #cbd3cc; +} + +.machine-code em { + color: var(--lime); + font-style: normal; +} + +.code-dim { + display: inline-block; + width: 24px; + color: #434b44; +} + +.machine-core-wrap { + position: relative; + display: grid; + min-height: 226px; + place-items: center; +} + +.machine-core { + width: 226px; + filter: drop-shadow(0 0 28px rgba(167, 255, 117, 0.08)); +} + +.core-label { + position: absolute; + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; +} + +.core-label strong { + font-size: 0.94rem; + font-weight: 500; +} + +.core-label span { + color: var(--text-dim); + font-size: 0.52rem; + letter-spacing: 0.14em; +} + +.machine-output { + padding: 16px; + border: 1px solid var(--line); + border-radius: 12px; + background: rgba(0, 0, 0, 0.2); +} + +.output-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 0; + color: var(--text-dim); + font-size: 0.6rem; +} + +.output-row b { + color: #d6ddd7; + font-weight: 400; +} + +.output-signal { + display: flex; + align-items: flex-end; + gap: 4px; + height: 28px; + padding-top: 10px; + margin-top: 8px; + border-top: 1px solid var(--line); +} + +.output-signal span { + flex: 1; + height: 100%; + border-radius: 2px 2px 0 0; + background: linear-gradient(to top, rgba(167, 255, 117, 0.18), var(--lime)); + transform-origin: bottom; +} + +.machine-footer { + min-height: 50px; + border-top: 1px solid var(--line); +} + +.machine-footer > span:first-child { + display: inline-flex; + align-items: center; + gap: 8px; + color: #c4cbc5; +} + +.status-dot { + width: 6px; + aspect-ratio: 1; + border-radius: 50%; + background: var(--lime); + box-shadow: 0 0 12px var(--lime); +} + +.signal-tape { + overflow: hidden; + padding: 15px 0; + color: var(--text-dim); + border-top: 1px solid var(--line); + border-bottom: 1px solid var(--line); + font-size: 0.62rem; + letter-spacing: 0.12em; +} + +.signal-tape-track { + display: flex; + align-items: center; + gap: 28px; + width: max-content; + animation: tape 30s linear infinite; +} + +.signal-tape-track i { + width: 4px; + aspect-ratio: 1; + border-radius: 50%; + background: var(--lime); +} diff --git a/website/src/styles/landing-system.css b/website/src/styles/landing-system.css new file mode 100644 index 00000000..1e6cc181 --- /dev/null +++ b/website/src/styles/landing-system.css @@ -0,0 +1,323 @@ +.system-section, +.native-section, +.closing { + padding-top: clamp(120px, 14vw, 210px); +} + +.section-heading { + display: grid; + grid-template-columns: 0.72fr 1.4fr 0.9fr; + gap: 54px; + align-items: start; +} + +.section-index { + color: var(--lime); + font-size: 0.64rem; + letter-spacing: 0.12em; +} + +.section-heading h2, +.pipeline-sticky h2, +.native-copy h2, +.closing h2 { + font-size: clamp(2.7rem, 5vw, 5.2rem); + font-weight: 500; + letter-spacing: -0.065em; + line-height: 0.98; +} + +.section-heading > p:last-child, +.pipeline-sticky > p, +.native-copy > p, +.closing-side > p { + color: var(--text-muted); + font-size: 0.98rem; + line-height: 1.75; +} + +.layer-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1px; + margin-top: 86px; + border: 1px solid var(--line); + border-radius: 22px; + background: var(--line); + overflow: hidden; +} + +.layer-card { + position: relative; + min-height: 390px; + padding: 28px; + background: var(--bg); + transition: background 0.4s ease; +} + +.layer-card::after { + position: absolute; + inset: 0; + pointer-events: none; + content: ''; + opacity: 0; + background: radial-gradient(circle at 80% 10%, rgba(167, 255, 117, 0.12), transparent 36%); + transition: opacity 0.4s ease; +} + +.layer-card:hover { + background: var(--bg-raised); +} + +.layer-card:hover::after { + opacity: 1; +} + +.layer-card-top { + position: relative; + z-index: 1; + display: flex; + justify-content: space-between; + color: var(--text-dim); + font-size: 0.58rem; + letter-spacing: 0.1em; +} + +.layer-card-icon { + position: relative; + z-index: 1; + width: 76px; + height: 76px; + margin: 46px 0 38px; +} + +.layer-card-icon span { + position: absolute; + inset: 0; + border: 1px solid var(--line-strong); + border-radius: 18px; + transition: transform 0.5s var(--ease-out), border-color 0.4s ease; +} + +.layer-card-icon span:nth-child(2) { + transform: translate(9px, 9px); +} + +.layer-card-icon span:nth-child(3) { + transform: translate(18px, 18px); + border-color: rgba(167, 255, 117, 0.35); +} + +.layer-card:hover .layer-card-icon span:first-child { + transform: rotate(-6deg) translate(-4px, -4px); +} + +.layer-card:hover .layer-card-icon span:nth-child(2) { + transform: rotate(4deg) translate(9px, 9px); +} + +.layer-card:hover .layer-card-icon span:nth-child(3) { + transform: rotate(10deg) translate(18px, 18px); + border-color: var(--lime); +} + +.layer-card h3 { + position: relative; + z-index: 1; + max-width: 480px; + font-size: clamp(1.65rem, 2.8vw, 2.65rem); + font-weight: 500; + letter-spacing: -0.045em; + line-height: 1.08; +} + +.layer-card > p { + position: relative; + z-index: 1; + max-width: 540px; + margin-top: 18px; + color: var(--text-muted); + font-size: 0.9rem; + line-height: 1.7; +} + +.layer-signal { + position: relative; + z-index: 1; + display: flex; + align-items: center; + justify-content: space-between; + padding-top: 20px; + margin-top: 28px; + color: var(--text-dim); + border-top: 1px solid var(--line); + font-size: 0.62rem; +} + +.layer-signal svg { + width: 16px; + color: var(--lime); + transition: transform 0.35s var(--ease-out); +} + +.layer-card:hover .layer-signal svg { + transform: translateX(5px); +} + +.pipeline-section { + padding: clamp(140px, 16vw, 240px) 0; +} + +.pipeline-layout { + display: grid; + grid-template-columns: 0.82fr 1.18fr; + gap: clamp(60px, 10vw, 160px); + align-items: start; +} + +.pipeline-sticky { + position: sticky; + top: 130px; +} + +.pipeline-sticky h2 { + margin-top: 24px; +} + +.pipeline-sticky > p { + max-width: 470px; + margin-top: 26px; +} + +.pipeline-key { + display: flex; + flex-wrap: wrap; + gap: 18px; + margin-top: 34px; + color: var(--text-dim); + font-size: 0.58rem; + letter-spacing: 0.08em; +} + +.pipeline-key span { + display: inline-flex; + align-items: center; + gap: 8px; +} + +.pipeline-key i { + width: 7px; + aspect-ratio: 1; + border-radius: 50%; +} + +.key-pre { + background: var(--ice); +} + +.key-core { + background: var(--lime); +} + +.stage-list { + position: relative; +} + +.stage-list::before { + position: absolute; + top: 0; + bottom: 0; + right: 15px; + width: 1px; + content: ''; + background: var(--line); +} + +.stage { + position: relative; + display: grid; + grid-template-columns: 54px 1fr 32px; + gap: 18px; + padding: 27px 0; + border-top: 1px solid var(--line); +} + +.stage:last-child { + border-bottom: 1px solid var(--line); +} + +.stage-number { + padding-top: 6px; + color: var(--text-dim); + font-size: 0.62rem; +} + +.stage-title-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 18px; +} + +.stage h3 { + font-size: clamp(1.35rem, 2.1vw, 2rem); + font-weight: 500; + letter-spacing: -0.035em; +} + +.stage-phase { + padding: 5px 7px; + border: 1px solid var(--line); + border-radius: 6px; + font-size: 0.5rem; + letter-spacing: 0.08em; +} + +.phase-pre { + color: var(--ice); +} + +.phase-core { + color: var(--lime); +} + +.stage p { + max-width: 590px; + margin-top: 10px; + color: var(--text-muted); + font-size: 0.84rem; + line-height: 1.65; +} + +.stage code { + display: inline-block; + margin-top: 13px; + color: var(--text-dim); + font-family: var(--font-mono); + font-size: 0.58rem; +} + +.stage-node { + position: relative; + z-index: 2; + display: grid; + width: 31px; + height: 31px; + place-items: center; + border: 1px solid var(--line); + border-radius: 50%; + background: var(--bg); +} + +.stage-node span { + width: 7px; + aspect-ratio: 1; + border-radius: 50%; + background: var(--lime); + transition: box-shadow 0.3s ease, transform 0.3s ease; +} + +.stage:hover .stage-node span { + transform: scale(1.35); + box-shadow: 0 0 18px var(--lime); +}