+ {/* Video Selector */}
+
+
Choose a video:
+
+ {DEMO_VIDEOS.map((video) => (
+ handleVideoSelect(video)}
+ type="button">
+ {video.label}
+
+ ))}
+
+
+
+ {/* Video Element (hidden, used by adapters) */}
+
+
+
+ Video: {selectedVideo.credit}
+
+
+
+ {/* GIFit Editor */}
+ {videoReady && (
+
+ )}
+
+ {!videoReady && (
+
+ Loading video...
+
+ )}
+
+ );
+}
diff --git a/landing/src/LandingPage.module.css b/landing/src/LandingPage.module.css
new file mode 100644
index 0000000..b067135
--- /dev/null
+++ b/landing/src/LandingPage.module.css
@@ -0,0 +1,272 @@
+.page {
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+/* --- Navigation --- */
+
+.nav {
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ background: rgba(10, 10, 10, 0.8);
+ backdrop-filter: blur(12px);
+ border-bottom: 1px solid var(--landing_border);
+}
+
+.navInner {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0.75rem 1.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.navLogo {
+ height: 1.5rem;
+ color: white;
+}
+
+.navLinks {
+ display: flex;
+ gap: 1.5rem;
+ font-size: 0.875rem;
+ font-weight: 500;
+}
+
+.navLinks a {
+ text-decoration: none;
+ color: var(--landing_text_muted);
+ transition: color 200ms;
+}
+
+.navLinks a:hover {
+ color: white;
+}
+
+/* --- Hero --- */
+
+.hero {
+ padding: 6rem 1.5rem 4rem;
+ text-align: center;
+}
+
+.heroInner {
+ max-width: 720px;
+ margin: 0 auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1.25rem;
+}
+
+.badge {
+ display: inline-block;
+ font-size: 0.75rem;
+ font-weight: 600;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--landing_accent);
+ border: 1px solid rgba(235, 10, 30, 0.3);
+ border-radius: 999px;
+ padding: 0.375rem 1rem;
+ background: rgba(235, 10, 30, 0.08);
+}
+
+.heroTitle {
+ font-size: clamp(2rem, 6vw, 3.5rem);
+ font-weight: 800;
+ line-height: 1.1;
+ letter-spacing: -0.03em;
+ color: white;
+ text-wrap: balance;
+}
+
+.heroSubtitle {
+ font-size: 1.125rem;
+ line-height: 1.6;
+ color: var(--landing_text_muted);
+ max-width: 560px;
+ text-wrap: pretty;
+}
+
+.heroCta {
+ display: flex;
+ gap: 0.75rem;
+ margin-top: 0.5rem;
+}
+
+.ctaPrimary {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.625rem 1.5rem;
+ background: var(--landing_accent);
+ color: white;
+ border-radius: 8px;
+ text-decoration: none;
+ font-weight: 600;
+ font-size: 0.875rem;
+ transition: opacity 200ms;
+}
+
+.ctaPrimary:hover {
+ opacity: 0.85;
+}
+
+.ctaSecondary {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.625rem 1.5rem;
+ background: transparent;
+ color: white;
+ border: 1px solid var(--landing_border);
+ border-radius: 8px;
+ text-decoration: none;
+ font-weight: 600;
+ font-size: 0.875rem;
+ transition: border-color 200ms, background 200ms;
+}
+
+.ctaSecondary:hover {
+ border-color: rgba(255, 255, 255, 0.3);
+ background: rgba(255, 255, 255, 0.04);
+}
+
+/* --- Features --- */
+
+.features {
+ padding: 4rem 1.5rem;
+ border-top: 1px solid var(--landing_border);
+}
+
+.featuresInner {
+ max-width: 1000px;
+ margin: 0 auto;
+}
+
+.sectionTitle {
+ font-size: 1.75rem;
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ text-align: center;
+ margin-bottom: 2.5rem;
+ color: white;
+}
+
+.featureGrid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
+}
+
+@media (max-width: 640px) {
+ .featureGrid {
+ grid-template-columns: 1fr;
+ }
+}
+
+.featureCard {
+ padding: 1.5rem;
+ border: 1px solid var(--landing_border);
+ border-radius: 12px;
+ background: var(--landing_surface);
+ transition: border-color 300ms;
+}
+
+.featureCard:hover {
+ border-color: rgba(255, 255, 255, 0.15);
+}
+
+.featureTitle {
+ font-size: 1rem;
+ font-weight: 600;
+ margin-bottom: 0.5rem;
+ color: white;
+}
+
+.featureDescription {
+ font-size: 0.875rem;
+ line-height: 1.5;
+ color: var(--landing_text_muted);
+}
+
+/* --- Demo Section --- */
+
+.demoSection {
+ padding: 4rem 1.5rem 6rem;
+ border-top: 1px solid var(--landing_border);
+}
+
+.demoInner {
+ max-width: 1000px;
+ margin: 0 auto;
+}
+
+.demoSubtitle {
+ text-align: center;
+ font-size: 1rem;
+ color: var(--landing_text_muted);
+ margin-bottom: 2rem;
+ margin-top: -1rem;
+}
+
+/* --- Footer --- */
+
+.footer {
+ border-top: 1px solid var(--landing_border);
+ padding: 1.5rem;
+}
+
+.footerInner {
+ max-width: 1200px;
+ margin: 0 auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 0.75rem;
+ color: var(--landing_text_muted);
+}
+
+@media (max-width: 640px) {
+ .footerInner {
+ flex-direction: column;
+ gap: 0.75rem;
+ text-align: center;
+ }
+}
+
+.footerCredit {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ color: var(--landing_text_muted);
+ text-decoration: none;
+}
+
+.footerCredit:hover {
+ color: white;
+}
+
+.tkLogo {
+ height: 1em;
+}
+
+.footerSupport {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-style: italic;
+}
+
+.bugIcon {
+ color: var(--landing_accent);
+ width: 1em;
+ height: 1em;
+}
+
+.footerVersion {
+ letter-spacing: 0.075em;
+ font-variant-numeric: tabular-nums;
+}
diff --git a/landing/src/LandingPage.tsx b/landing/src/LandingPage.tsx
new file mode 100644
index 0000000..60ac037
--- /dev/null
+++ b/landing/src/LandingPage.tsx
@@ -0,0 +1,127 @@
+import css from './LandingPage.module.css';
+import { DemoSection } from './DemoSection';
+import GIFitLogo from '@/assets/gifit-logo.svg?react';
+import TKLogo from '@/assets/tk.svg?react';
+import BugIcon from '@/assets/bug.svg?react';
+
+export function LandingPage() {
+ return (
+