Skip to main content

logicaffeine_web/ui/pages/
landing.rs

1//! Marketing landing page.
2//!
3//! The main entry point for new visitors showcasing the LOGOS platform with:
4//! - Hero section with animated gradient orbs
5//! - Feature highlights for Logic, Code, and Math modes
6//! - Call-to-action buttons for learning and the studio
7//! - Live interactive demos
8//!
9//! # Route
10//!
11//! Accessed via [`Route::Landing`].
12
13use dioxus::prelude::*;
14#[cfg(all(feature = "split", target_arch = "wasm32"))]
15use dioxus::wasm_split;
16use crate::ui::router::Route;
17use crate::ui::components::main_nav::{MainNav, ActivePage};
18use crate::ui::components::footer::Footer;
19use crate::ui::components::icon::{Icon, IconVariant, IconSize};
20use crate::ui::components::code_editor::{CodeEditor, Language};
21use crate::ui::seo::{JsonLdMultiple, PageHead, organization_schema, website_schema, faq_schema, pages as seo_pages};
22use crate::ui::state::StudioMode;
23use logicaffeine_compile::{compile_for_ui, compile_theorem_for_ui, interpret_for_ui, generate_rust_code};
24use logicaffeine_kernel::interface::Repl;
25use crate::ui::examples::{
26    CODE_HELLO, CODE_FIBONACCI, CODE_CRDT_COUNTERS, CODE_CRDT_TALLY,
27    LOGIC_LEIBNIZ, LOGIC_BARBER, LOGIC_SIMPLE, LOGIC_QUANTIFIERS,
28    MATH_GODEL_LITERATE, MATH_INCOMPLETENESS_LITERATE, MATH_AUTO, MATH_NAT, MATH_BOOL, MATH_PROP_LOGIC,
29};
30
31struct DemoExample {
32    filename: &'static str,
33    icon: &'static str,
34    content: &'static str,
35    output: &'static str,
36    compiled: &'static str,
37    studio_path: &'static str,
38}
39
40const CODE_DEMO_EXAMPLES: [DemoExample; 4] = [
41    DemoExample {
42        filename: "hello-world.logos",
43        icon: "λ",
44        content: CODE_HELLO,
45        output: "",
46        compiled: "",
47        studio_path: "examples/code/hello-world.logos",
48    },
49    DemoExample {
50        filename: "fibonacci.logos",
51        icon: "λ",
52        content: CODE_FIBONACCI,
53        output: "",
54        compiled: "",
55        studio_path: "examples/code/fibonacci.logos",
56    },
57    DemoExample {
58        filename: "counters.logos",
59        icon: "λ",
60        content: CODE_CRDT_COUNTERS,
61        output: "",
62        compiled: "",
63        studio_path: "examples/code/distributed/counters.logos",
64    },
65    DemoExample {
66        filename: "tally.logos",
67        icon: "λ",
68        content: CODE_CRDT_TALLY,
69        output: "",
70        compiled: "",
71        studio_path: "examples/code/distributed/tally.logos",
72    },
73];
74
75const LOGIC_DEMO_EXAMPLES: [DemoExample; 4] = [
76    DemoExample {
77        filename: "leibniz-identity.logic",
78        icon: "∀",
79        content: LOGIC_LEIBNIZ,
80        output: "",
81        compiled: "",
82        studio_path: "examples/logic/leibniz-identity.logic",
83    },
84    DemoExample {
85        filename: "barber-paradox.logic",
86        icon: "∀",
87        content: LOGIC_BARBER,
88        output: "",
89        compiled: "",
90        studio_path: "examples/logic/barber-paradox.logic",
91    },
92    DemoExample {
93        filename: "simple-sentences.logic",
94        icon: "∀",
95        content: LOGIC_SIMPLE,
96        output: "",
97        compiled: "",
98        studio_path: "examples/logic/simple-sentences.logic",
99    },
100    DemoExample {
101        filename: "quantifiers.logic",
102        icon: "∀",
103        content: LOGIC_QUANTIFIERS,
104        output: "",
105        compiled: "",
106        studio_path: "examples/logic/quantifiers.logic",
107    },
108];
109
110const MATH_DEMO_EXAMPLES: [DemoExample; 6] = [
111    DemoExample {
112        filename: "godel-literate.logos",
113        icon: "π",
114        content: MATH_GODEL_LITERATE,
115        output: "",
116        compiled: "",
117        studio_path: "examples/math/godel-literate.logos",
118    },
119    DemoExample {
120        filename: "incompleteness-literate.logos",
121        icon: "π",
122        content: MATH_INCOMPLETENESS_LITERATE,
123        output: "",
124        compiled: "",
125        studio_path: "examples/math/incompleteness-literate.logos",
126    },
127    DemoExample {
128        filename: "auto-tactic.logos",
129        icon: "π",
130        content: MATH_AUTO,
131        output: "",
132        compiled: "",
133        studio_path: "examples/math/auto-tactic.logos",
134    },
135    DemoExample {
136        filename: "natural-numbers.logos",
137        icon: "π",
138        content: MATH_NAT,
139        output: "",
140        compiled: "",
141        studio_path: "examples/math/natural-numbers.logos",
142    },
143    DemoExample {
144        filename: "boolean-logic.logos",
145        icon: "π",
146        content: MATH_BOOL,
147        output: "",
148        compiled: "",
149        studio_path: "examples/math/boolean-logic.logos",
150    },
151    DemoExample {
152        filename: "prop-logic.logos",
153        icon: "π",
154        content: MATH_PROP_LOGIC,
155        output: "",
156        compiled: "",
157        studio_path: "examples/math/prop-logic.logos",
158    },
159];
160
161fn execute_math_code(content: &str) -> (Vec<String>, Option<String>) {
162    let mut repl = Repl::new();
163    let mut lines = Vec::new();
164    let mut error = None;
165    let statements = parse_math_statements(content);
166    for stmt in statements {
167        match repl.execute(&stmt) {
168            Ok(output) => {
169                if !output.is_empty() {
170                    lines.push(output);
171                }
172            }
173            Err(e) => {
174                error = Some(e.to_string());
175                break;
176            }
177        }
178    }
179    (lines, error)
180}
181
182fn parse_math_statements(code: &str) -> Vec<String> {
183    let mut statements = Vec::new();
184    let lines: Vec<&str> = code.lines().collect();
185    let mut i = 0;
186
187    while i < lines.len() {
188        let line = lines[i];
189        let trimmed = line.trim();
190
191        if trimmed.is_empty() || trimmed.starts_with("--") {
192            i += 1;
193            continue;
194        }
195
196        if trimmed.starts_with("## To ") {
197            let mut block = String::new();
198            block.push_str(trimmed);
199            i += 1;
200            while i < lines.len() {
201                let next_line = lines[i];
202                let next_trimmed = next_line.trim();
203                if next_trimmed.is_empty() || next_trimmed.starts_with("--") {
204                    i += 1;
205                    continue;
206                }
207                let is_indented = next_line.starts_with(' ') || next_line.starts_with('\t');
208                let is_continuation = next_trimmed.starts_with("Consider ")
209                    || next_trimmed.starts_with("When ")
210                    || next_trimmed.starts_with("Yield ");
211                if is_indented || is_continuation {
212                    block.push(' ');
213                    block.push_str(next_trimmed);
214                    i += 1;
215                } else {
216                    break;
217                }
218            }
219            statements.push(block);
220            continue;
221        }
222
223        if trimmed.starts_with("## Theorem:") {
224            let mut block = String::new();
225            block.push_str(trimmed);
226            i += 1;
227            while i < lines.len() {
228                let next_line = lines[i];
229                let next_trimmed = next_line.trim();
230                if next_trimmed.is_empty() || next_trimmed.starts_with("--") {
231                    i += 1;
232                    continue;
233                }
234                let is_indented = next_line.starts_with(' ') || next_line.starts_with('\t');
235                let is_theorem_part = next_trimmed.starts_with("Statement:")
236                    || next_trimmed.starts_with("Proof:");
237                if is_indented || is_theorem_part {
238                    block.push('\n');
239                    block.push_str(next_line);
240                    i += 1;
241                    if next_trimmed.starts_with("Proof:") && next_trimmed.ends_with('.') {
242                        break;
243                    }
244                } else {
245                    break;
246                }
247            }
248            statements.push(block);
249            continue;
250        }
251
252        if (trimmed.starts_with("A ") || trimmed.starts_with("An ")) && trimmed.contains(" is either") {
253            if trimmed.ends_with('.') && !trimmed.trim_end_matches('.').ends_with(':') {
254                statements.push(trimmed.to_string());
255                i += 1;
256                continue;
257            }
258            let mut block = String::new();
259            block.push_str(trimmed);
260            i += 1;
261            while i < lines.len() {
262                let next_line = lines[i];
263                let next_trimmed = next_line.trim();
264                if next_trimmed.is_empty() || next_trimmed.starts_with("--") {
265                    i += 1;
266                    continue;
267                }
268                let is_indented = next_line.starts_with(' ') || next_line.starts_with('\t');
269                let looks_like_variant = next_trimmed.starts_with("a ")
270                    || next_trimmed.chars().next().map(|c| c.is_uppercase()).unwrap_or(false);
271                if is_indented || (looks_like_variant && !next_trimmed.starts_with("A ") && !next_trimmed.starts_with("An ")) {
272                    if !block.ends_with(':') {
273                        block.push_str(" or ");
274                    } else {
275                        block.push(' ');
276                    }
277                    block.push_str(next_trimmed.trim_end_matches('.'));
278                    i += 1;
279                } else {
280                    break;
281                }
282            }
283            if !block.ends_with('.') {
284                block.push('.');
285            }
286            statements.push(block);
287            continue;
288        }
289
290        let mut current_stmt = String::new();
291        while i < lines.len() {
292            let line = lines[i];
293            let trimmed = line.trim();
294            if trimmed.is_empty() || trimmed.starts_with("--") {
295                i += 1;
296                continue;
297            }
298            if !current_stmt.is_empty() {
299                current_stmt.push(' ');
300            }
301            current_stmt.push_str(trimmed);
302            i += 1;
303            if trimmed.ends_with('.') {
304                break;
305            }
306        }
307        if !current_stmt.is_empty() {
308            statements.push(current_stmt);
309        }
310    }
311
312    statements
313}
314
315fn examples_for_mode(mode: StudioMode) -> &'static [DemoExample] {
316    match mode {
317        StudioMode::Code => &CODE_DEMO_EXAMPLES,
318        // The landing carousel surfaces Logic/Code/Math; Hardware lives in the Studio.
319        StudioMode::Logic | StudioMode::Hardware => &LOGIC_DEMO_EXAMPLES,
320        StudioMode::Math => &MATH_DEMO_EXAMPLES,
321    }
322}
323
324const LANDING_STYLE: &str = r#"
325body:has(.landing) {
326  overflow: hidden;
327}
328
329.landing {
330  height: 100vh;
331  color: var(--text-primary);
332  background:
333    radial-gradient(1200px 600px at 50% -120px, rgba(167,139,250,0.18), transparent 60%),
334    radial-gradient(900px 500px at 15% 30%, rgba(96,165,250,0.18), transparent 60%),
335    radial-gradient(800px 450px at 90% 45%, rgba(34,197,94,0.10), transparent 62%),
336    linear-gradient(180deg, #070a12, #0b1022 55%, #070a12);
337  overflow-x: hidden;
338  overflow-y: auto;
339  font-family: var(--font-sans);
340  position: relative;
341}
342
343.bg-orb {
344  position: absolute;
345  inset: auto;
346  width: 520px;
347  height: 520px;
348  border-radius: var(--radius-full);
349  filter: blur(42px);
350  opacity: 0.22;
351  pointer-events: none;
352  animation: float 14s ease-in-out infinite, pulse-glow 10s ease-in-out infinite;
353}
354.orb1 { top: -220px; left: -160px; background: radial-gradient(circle at 30% 30%, var(--color-accent-blue), transparent 60%); animation-delay: 0s; }
355.orb2 { top: 120px; right: -200px; background: radial-gradient(circle at 40% 35%, var(--color-accent-purple), transparent 60%); animation-delay: -5s; }
356.orb3 { bottom: -260px; left: 20%; background: radial-gradient(circle at 40% 35%, rgba(34,197,94,0.9), transparent 60%); animation-delay: -10s; }
357
358.container {
359  width: 100%;
360  max-width: 1120px;
361  margin: 0 auto;
362  padding: 0 var(--spacing-xl);
363}
364
365/* Navigation now handled by MainNav component */
366
367.btn {
368  display: inline-flex;
369  align-items: center;
370  justify-content: center;
371  gap: 10px;
372  padding: var(--spacing-md) var(--spacing-lg);
373  border-radius: var(--radius-lg);
374  border: 1px solid rgba(255,255,255,0.10);
375  background: rgba(255,255,255,0.05);
376  text-decoration: none;
377  font-weight: 650;
378  font-size: var(--font-body-md);
379  transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease;
380  will-change: transform;
381}
382.btn:hover { transform: translateY(-1px); background: rgba(255,255,255,0.07); border-color: rgba(255,255,255,0.18); }
383.btn:active { transform: translateY(0px); }
384
385.btn-primary {
386  background: linear-gradient(135deg, rgba(96,165,250,0.95), rgba(167,139,250,0.95));
387  border-color: rgba(255,255,255,0.20);
388  color: #060814;
389  box-shadow: 0 18px 40px rgba(96,165,250,0.18);
390}
391.btn-primary:hover {
392  background: linear-gradient(135deg, var(--color-accent-blue), var(--color-accent-purple));
393}
394
395.btn-ghost {
396  background: rgba(255,255,255,0.03);
397}
398
399.btn-icon {
400  padding: 10px;
401  background: rgba(255,255,255,0.03);
402}
403.btn-icon svg {
404  width: 20px;
405  height: 20px;
406  fill: currentColor;
407}
408
409.github-link {
410  display: inline-flex;
411  align-items: center;
412  gap: 6px;
413  color: inherit;
414  text-decoration: none;
415  transition: color 0.2s ease;
416}
417.github-link:hover {
418  color: var(--text-primary);
419}
420
421.hero {
422  padding: 64px 0 30px;
423}
424
425.hero-grid {
426  display: grid;
427  grid-template-columns: 1.05fr 0.95fr;
428  gap: 36px;
429  align-items: center;
430}
431
432.badge {
433  display: inline-flex;
434  align-items: center;
435  gap: 10px;
436  padding: 10px 14px;
437  border-radius: var(--radius-full);
438  background: rgba(255,255,255,0.06);
439  border: 1px solid rgba(255,255,255,0.10);
440  backdrop-filter: blur(18px);
441  box-shadow: 0 18px 40px rgba(0,0,0,0.25);
442  color: var(--text-primary);
443  font-size: var(--font-caption-md);
444  font-weight: 650;
445}
446.badge .dot {
447  width: 8px;
448  height: 8px;
449  border-radius: var(--radius-full);
450  background: var(--color-success);
451  box-shadow: 0 0 0 6px rgba(34,197,94,0.12);
452  animation: pulse-glow 2s ease-in-out infinite;
453}
454
455.hero .badge { animation: fadeInUp 0.6s ease both; }
456.hero .h-title { animation: fadeInUp 0.6s ease 0.08s both; }
457.hero .h-sub { animation: fadeInUp 0.6s ease 0.16s both; }
458.hero .hero-ctas { animation: fadeInUp 0.6s ease 0.24s both; }
459.hero .microcopy { animation: fadeInUp 0.6s ease 0.30s both; }
460.hero .demo { animation: fadeInUp 0.8s ease 0.44s both; }
461
462.h-title {
463  margin: 24px 0 var(--spacing-lg);
464  font-size: var(--font-display-xl);
465  line-height: 1.15;
466  letter-spacing: -2px;
467  font-weight: 900;
468  background: linear-gradient(180deg, #ffffff 0%, rgba(229,231,235,0.78) 65%, rgba(229,231,235,0.62) 100%);
469  -webkit-background-clip: text;
470  -webkit-text-fill-color: transparent;
471}
472
473.h-sub {
474  margin: 0 0 var(--spacing-xl);
475  max-width: 580px;
476  color: var(--text-secondary);
477  font-size: var(--font-body-lg);
478  line-height: 1.65;
479}
480
481.hero-ctas {
482  display: flex;
483  gap: var(--spacing-md);
484  flex-wrap: wrap;
485  margin: 18px 0 14px;
486}
487
488.microcopy {
489  font-size: var(--font-caption-md);
490  color: var(--text-tertiary);
491}
492
493.demo {
494  border-radius: var(--radius-xl);
495  border: 1px solid rgba(255,255,255,0.10);
496  background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.03));
497  backdrop-filter: blur(18px);
498  box-shadow: 0 30px 80px rgba(0,0,0,0.55);
499  overflow: hidden;
500  position: relative;
501}
502
503.demo::before {
504  content: "";
505  position: absolute;
506  inset: -2px;
507  background: radial-gradient(600px 280px at 10% 10%, rgba(96,165,250,0.22), transparent 55%),
508              radial-gradient(520px 240px at 90% 20%, rgba(167,139,250,0.22), transparent 55%);
509  opacity: 0.9;
510  pointer-events: none;
511}
512
513.demo-head {
514  position: relative;
515  display: flex;
516  align-items: center;
517  justify-content: space-between;
518  padding: 14px var(--spacing-lg);
519  border-bottom: 1px solid rgba(255,255,255,0.06);
520  background: rgba(0,0,0,0.10);
521}
522
523.win-dots { display: flex; gap: var(--spacing-sm); align-items: center; }
524.wdot { width: 11px; height: 11px; border-radius: var(--radius-full); opacity: 0.9; }
525.wr { background: #ef4444; } .wy { background: #fbbf24; } .wg { background: #22c55e; }
526
527.demo-label {
528  font-size: var(--font-caption-sm);
529  color: var(--text-secondary);
530  border: 1px solid rgba(255,255,255,0.10);
531  padding: 7px 10px;
532  border-radius: var(--radius-full);
533  background: rgba(255,255,255,0.04);
534}
535
536.demo-body {
537  position: relative;
538  display: grid;
539  grid-template-columns: 1fr 1fr;
540}
541
542.demo-col {
543  padding: 18px 18px 22px;
544  min-height: 240px;
545}
546
547.demo-col + .demo-col {
548  border-left: 1px solid rgba(255,255,255,0.06);
549  background: rgba(0,0,0,0.18);
550}
551
552.demo-kicker {
553  display: flex;
554  align-items: center;
555  justify-content: space-between;
556  margin-bottom: var(--spacing-md);
557  font-size: var(--font-caption-sm);
558  color: var(--text-secondary);
559}
560
561.pill {
562  border: 1px solid rgba(255,255,255,0.10);
563  background: rgba(255,255,255,0.04);
564  padding: 6px 10px;
565  border-radius: var(--radius-full);
566}
567
568.code {
569  font-family: var(--font-mono);
570  font-size: var(--font-caption-md);
571  line-height: 1.6;
572  color: var(--text-primary);
573  white-space: pre-wrap;
574}
575
576.code.logic { color: var(--color-accent-purple); }
577
578.demo-foot {
579  display: flex;
580  gap: 10px;
581  flex-wrap: wrap;
582  padding: 14px var(--spacing-lg);
583  border-top: 1px solid rgba(255,255,255,0.06);
584  background: rgba(0,0,0,0.12);
585  color: var(--text-secondary);
586  font-size: var(--font-caption-md);
587}
588
589.section {
590  padding: 74px 0;
591}
592
593.section-title {
594  font-size: var(--font-display-md);
595  letter-spacing: -1.2px;
596  margin: 0 0 14px;
597  font-weight: 800;
598}
599.section-sub {
600  margin: 0 0 var(--spacing-xl);
601  color: var(--text-secondary);
602  line-height: 1.65;
603  max-width: 760px;
604}
605.section-right .section-title,
606.section-right .section-sub {
607  text-align: right;
608}
609.section-right .section-sub {
610  margin-left: auto;
611}
612.section-center .section-title,
613.section-center .section-sub {
614  text-align: center;
615}
616.section-center .section-sub {
617  margin-left: auto;
618  margin-right: auto;
619}
620
621.grid3 {
622  display: grid;
623  grid-template-columns: repeat(3, 1fr);
624  gap: 18px;
625}
626.grid2 {
627  display: grid;
628  grid-template-columns: 1fr 1fr;
629  gap: 18px;
630}
631
632.card {
633  position: relative;
634  border-radius: var(--radius-xl);
635  border: 1px solid rgba(255,255,255,0.10);
636  background: rgba(255,255,255,0.04);
637  backdrop-filter: blur(18px);
638  padding: 18px;
639  transition: transform 0.18s ease, border-color 0.18s ease, background 0.18s ease;
640  overflow: hidden;
641}
642.card::before {
643  content: "";
644  position: absolute;
645  inset: 0;
646  border-radius: var(--radius-xl);
647  background: linear-gradient(135deg, rgba(96,165,250,0.12), rgba(167,139,250,0.12));
648  opacity: 0;
649  transition: opacity 0.3s ease;
650  pointer-events: none;
651}
652.card:hover {
653  transform: translateY(-3px);
654  border-color: rgba(167,139,250,0.28);
655  background: rgba(255,255,255,0.06);
656}
657.card:hover::before {
658  opacity: 1;
659}
660
661.icon-box {
662  width: 48px; height: 48px;
663  border-radius: var(--radius-lg);
664  display: flex;
665  align-items: center;
666  justify-content: center;
667  background: rgba(255,255,255,0.06);
668  border: 1px solid rgba(255,255,255,0.10);
669  margin-bottom: var(--spacing-md);
670}
671
672.icon-box .icon {
673  width: 24px;
674  height: 24px;
675}
676
677.card h3 {
678  margin: 0 0 var(--spacing-sm);
679  font-size: var(--font-body-md);
680  letter-spacing: -0.2px;
681}
682.card p {
683  margin: 0;
684  color: var(--text-secondary);
685  line-height: 1.6;
686  font-size: var(--font-body-md);
687}
688
689.quote {
690  font-size: var(--font-body-md);
691  line-height: 1.65;
692  color: var(--text-primary);
693}
694.quoter {
695  margin-top: 10px;
696  color: var(--text-tertiary);
697  font-size: var(--font-caption-md);
698}
699
700
701.tech-stack {
702  display: flex;
703  gap: 10px;
704  flex-wrap: wrap;
705  margin-top: 14px;
706}
707
708.tech-badge {
709  font-size: var(--font-caption-sm);
710  padding: 6px var(--spacing-md);
711  border-radius: 6px;
712  background: rgba(255,255,255,0.03);
713  border: 1px solid rgba(255,255,255,0.08);
714  color: var(--text-secondary);
715}
716
717.tech-badge.rust {
718  background: linear-gradient(135deg, rgba(183,65,14,0.15), rgba(222,165,132,0.10));
719  border-color: rgba(222,165,132,0.3);
720  color: #dea584;
721}
722
723.hello-world-layout {
724  display: flex;
725  flex-direction: column;
726  align-items: center;
727  gap: 40px;
728}
729
730.hello-pill-wrap,
731.hello-cta-wrap {
732  text-align: center;
733}
734
735.hello-editor {
736  width: 100%;
737  max-width: 820px;
738  border-radius: var(--radius-lg);
739  border: 1px solid rgba(255,255,255,0.10);
740  background: rgba(0,0,0,0.3);
741  overflow: hidden;
742  backdrop-filter: blur(8px);
743}
744
745.hello-loading {
746  width: 100%;
747  max-width: 820px;
748  min-height: 305px;
749}
750
751.hello-editor-head {
752  display: flex;
753  align-items: center;
754  justify-content: space-between;
755  padding: 10px 14px;
756  background: rgba(255,255,255,0.03);
757  border-bottom: 1px solid rgba(255,255,255,0.06);
758}
759
760.hello-editor-head .hello-filename {
761  font-size: var(--font-caption-sm);
762  color: var(--text-secondary);
763  font-family: var(--font-mono);
764}
765
766.hello-run-btn {
767  display: inline-flex;
768  align-items: center;
769  gap: 6px;
770  padding: 5px 14px;
771  border-radius: var(--radius-sm);
772  border: 1px solid rgba(52,211,153,0.4);
773  background: rgba(52,211,153,0.10);
774  color: #34d399;
775  font-size: var(--font-caption-sm);
776  font-weight: 600;
777  cursor: pointer;
778  transition: background 0.2s, border-color 0.2s;
779}
780
781.hello-run-btn:hover {
782  background: rgba(52,211,153,0.20);
783  border-color: rgba(52,211,153,0.6);
784}
785
786.hello-run-btn:disabled {
787  opacity: 0.5;
788  cursor: not-allowed;
789}
790
791.hello-editor-body {
792  display: flex;
793  min-height: 260px;
794}
795
796.hello-editor-left {
797  flex: 1;
798  min-width: 0;
799}
800
801.hello-editor-right {
802  flex: 1;
803  min-width: 0;
804  border-left: 1px solid rgba(255,255,255,0.06);
805  display: flex;
806  flex-direction: column;
807}
808
809.hello-output-head {
810  padding: 8px 14px;
811  font-size: var(--font-caption-sm);
812  color: var(--text-secondary);
813  font-family: var(--font-mono);
814  background: rgba(255,255,255,0.02);
815  border-bottom: 1px solid rgba(255,255,255,0.04);
816  text-transform: uppercase;
817  letter-spacing: 0.05em;
818}
819
820.hello-output-body {
821  padding: var(--spacing-md);
822  flex: 1;
823  overflow-y: auto;
824  font-family: var(--font-mono);
825  font-size: var(--font-body-md);
826  line-height: 1.6;
827}
828
829.hello-output-line {
830  margin: 0;
831  white-space: pre-wrap;
832  color: var(--text-primary);
833}
834
835.hello-output-error {
836  margin: 0;
837  white-space: pre-wrap;
838  color: var(--color-error, #f87171);
839}
840
841.hello-output-loading {
842  color: var(--text-secondary);
843  font-style: italic;
844}
845
846.hello-output-empty {
847  color: var(--text-secondary);
848  opacity: 0.5;
849}
850
851@media (max-width: 700px) {
852  .hello-editor-body {
853    flex-direction: column;
854  }
855  .hello-editor-right {
856    border-left: none;
857    border-top: 1px solid rgba(255,255,255,0.06);
858  }
859}
860
861.hello-note {
862  text-align: center;
863  font-size: var(--font-body-md);
864  color: var(--text-secondary);
865  display: inline-block;
866  padding: 8px 20px;
867  border: 1px solid rgba(167,139,250,0.3);
868  border-radius: var(--radius-full);
869  background: rgba(167,139,250,0.06);
870  box-shadow: 0 0 20px rgba(167,139,250,0.12), 0 0 40px rgba(96,165,250,0.08);
871}
872
873.compare-table {
874  display: flex;
875  flex-direction: column;
876  border-radius: var(--radius-lg);
877  border: 1px solid rgba(255,255,255,0.10);
878  overflow: hidden;
879  max-width: 800px;
880  margin: 0 auto;
881}
882
883.compare-row {
884  display: grid;
885  grid-template-columns: 1.2fr repeat(5, 1fr);
886}
887
888.compare-row.header {
889  background: rgba(255,255,255,0.05);
890  font-weight: 600;
891  font-size: var(--font-caption-md);
892}
893
894.compare-row:not(.header) {
895  border-top: 1px solid rgba(255,255,255,0.06);
896}
897
898.compare-cell {
899  padding: var(--spacing-md) 14px;
900  font-size: var(--font-caption-md);
901  color: var(--text-secondary);
902  text-align: center;
903}
904
905.compare-cell.label {
906  text-align: left;
907  color: var(--text-primary);
908  font-weight: 500;
909}
910
911.compare-cell.highlight {
912  background: rgba(167,139,250,0.08);
913  color: var(--color-accent-purple);
914  font-weight: 500;
915}
916
917.compare-row.header .compare-cell.highlight {
918  background: rgba(167,139,250,0.15);
919}
920
921@media (max-width: 700px) {
922  .compare-row {
923    grid-template-columns: 1fr 1fr 1fr;
924  }
925  .compare-cell:nth-child(4),
926  .compare-cell:nth-child(5),
927  .compare-cell:nth-child(6) {
928    display: none;
929  }
930}
931
932.faq-item {
933  padding: var(--spacing-lg) var(--spacing-lg) 14px;
934  border-radius: var(--radius-xl);
935  border: 1px solid rgba(255,255,255,0.10);
936  background: rgba(255,255,255,0.03);
937}
938.faq-q { font-weight: 750; margin-bottom: var(--spacing-sm); }
939.faq-a { color: var(--text-secondary); line-height: 1.6; font-size: var(--font-body-md); }
940
941.footer {
942  padding: 34px 0 44px;
943  border-top: 1px solid rgba(255,255,255,0.06);
944  color: var(--text-tertiary);
945  font-size: var(--font-caption-md);
946}
947
948.footer-row {
949  display: flex;
950  align-items: center;
951  justify-content: space-between;
952  gap: var(--spacing-lg);
953  flex-wrap: wrap;
954}
955
956@media (max-width: 980px) {
957  .hero-grid { grid-template-columns: 1fr; }
958  .demo-body { grid-template-columns: 1fr; }
959  .demo-col + .demo-col { border-left: none; border-top: 1px solid rgba(255,255,255,0.06); }
960  .grid3 { grid-template-columns: 1fr; }
961  .grid2 { grid-template-columns: 1fr; }
962  .h-title { font-size: var(--font-display-lg); }
963}
964
965@keyframes fadeInUp {
966  from { opacity: 0; transform: translateY(24px); }
967  to { opacity: 1; transform: translateY(0); }
968}
969
970@keyframes float {
971  0%, 100% { transform: translate3d(0, 0, 0); }
972  50% { transform: translate3d(0, -20px, 0); }
973}
974
975@keyframes pulse-glow {
976  0%, 100% { opacity: 0.22; }
977  50% { opacity: 0.32; }
978}
979
980@keyframes blink {
981  50% { opacity: 0; }
982}
983
984html { scroll-behavior: smooth; }
985
986.section + .section {
987  border-top: 1px solid rgba(255,255,255,0.04);
988}
989
990.steps {
991  display: flex;
992  align-items: center;
993  justify-content: center;
994  gap: var(--spacing-xl);
995  flex-wrap: wrap;
996}
997
998.step {
999  flex: 1;
1000  min-width: 200px;
1001  max-width: 280px;
1002  text-align: center;
1003  padding: var(--spacing-xl);
1004  border-radius: var(--radius-xl);
1005  background: rgba(255,255,255,0.04);
1006  border: 1px solid rgba(255,255,255,0.10);
1007  animation: fadeInUp 0.6s ease both;
1008}
1009
1010.step:nth-child(1) { animation-delay: 0s; }
1011.step:nth-child(3) { animation-delay: 0.1s; }
1012.step:nth-child(5) { animation-delay: 0.2s; }
1013
1014.step-num {
1015  width: 48px;
1016  height: 48px;
1017  margin: 0 auto var(--spacing-lg);
1018  border-radius: 50%;
1019  background: linear-gradient(135deg, var(--color-accent-blue), var(--color-accent-purple));
1020  color: #060814;
1021  font-weight: 800;
1022  font-size: var(--font-heading-sm);
1023  display: grid;
1024  place-items: center;
1025}
1026
1027.step h3 {
1028  margin: 0 0 var(--spacing-sm);
1029  font-size: var(--font-body-lg);
1030}
1031
1032.step p {
1033  margin: 0;
1034  color: var(--text-secondary);
1035  font-size: var(--font-body-md);
1036  line-height: 1.5;
1037}
1038
1039.step-arrow {
1040  font-size: 24px;
1041  color: var(--text-tertiary);
1042}
1043
1044.grid3 .card:nth-child(1) .icon-box { background: rgba(0,212,255,0.15); }
1045.grid3 .card:nth-child(2) .icon-box { background: rgba(129,140,248,0.15); }
1046.grid3 .card:nth-child(3) .icon-box { background: rgba(34,197,94,0.15); }
1047.grid3 .card:nth-child(4) .icon-box { background: rgba(251,191,36,0.15); }
1048.grid3 .card:nth-child(5) .icon-box { background: rgba(236,72,153,0.15); }
1049.grid3 .card:nth-child(6) .icon-box { background: rgba(129,140,248,0.15); }
1050
1051/* Mini-Studio */
1052.mini-studio {
1053  border-radius: var(--radius-xl);
1054  border: 1px solid rgba(255,255,255,0.10);
1055  background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.03));
1056  backdrop-filter: blur(18px);
1057  box-shadow: 0 30px 80px rgba(0,0,0,0.55);
1058  overflow: hidden;
1059  position: relative;
1060  display: flex;
1061  flex-direction: column;
1062  height: 635px;
1063}
1064.showcase-loading {
1065  min-height: 635px;
1066}
1067.mini-studio::before {
1068  content: "";
1069  position: absolute;
1070  inset: -2px;
1071  background: radial-gradient(600px 280px at 10% 10%, rgba(96,165,250,0.22), transparent 55%),
1072              radial-gradient(520px 240px at 90% 20%, rgba(167,139,250,0.22), transparent 55%);
1073  opacity: 0.9;
1074  pointer-events: none;
1075}
1076.mini-studio-head {
1077  position: relative;
1078  display: flex;
1079  align-items: center;
1080  justify-content: center;
1081  padding: 14px var(--spacing-lg);
1082  border-bottom: 1px solid rgba(255,255,255,0.06);
1083  background: rgba(0,0,0,0.10);
1084}
1085.mini-studio-head .win-dots {
1086  position: absolute;
1087  left: var(--spacing-lg);
1088}
1089.mini-mode-toggle {
1090  display: flex;
1091  gap: 4px;
1092  background: rgba(255,255,255,0.04);
1093  border: 1px solid rgba(255,255,255,0.10);
1094  border-radius: var(--radius-full);
1095  padding: 3px;
1096}
1097.mini-toggle-btn {
1098  padding: 6px 12px;
1099  border-radius: var(--radius-full);
1100  border: none;
1101  background: transparent;
1102  color: var(--text-secondary);
1103  font-size: var(--font-caption-sm);
1104  font-weight: 600;
1105  cursor: pointer;
1106  transition: background 0.18s, color 0.18s;
1107  display: flex;
1108  align-items: center;
1109  gap: 6px;
1110  font-family: inherit;
1111}
1112.mini-toggle-btn.active {
1113  background: rgba(96,165,250,0.2);
1114  color: var(--text-primary);
1115}
1116.mini-toggle-btn:hover:not(.active) {
1117  background: rgba(255,255,255,0.06);
1118}
1119.mini-studio-body {
1120  position: relative;
1121  display: grid;
1122  grid-template-columns: 180px 1fr;
1123  flex: 1;
1124  min-height: 0;
1125  overflow: hidden;
1126}
1127.mini-file-tabs {
1128  display: none;
1129  gap: 4px;
1130  padding: 8px 12px;
1131  overflow-x: auto;
1132  border-bottom: 1px solid rgba(255,255,255,0.06);
1133  background: rgba(0,0,0,0.08);
1134  flex-shrink: 0;
1135  -webkit-overflow-scrolling: touch;
1136}
1137.mini-file-tab {
1138  flex-shrink: 0;
1139  padding: 5px 10px;
1140  border-radius: var(--radius-full);
1141  border: 1px solid rgba(255,255,255,0.10);
1142  background: rgba(255,255,255,0.04);
1143  color: var(--text-secondary);
1144  font-size: var(--font-caption-sm);
1145  font-weight: 500;
1146  cursor: pointer;
1147  white-space: nowrap;
1148  font-family: var(--font-mono);
1149  transition: background 0.15s, color 0.15s, border-color 0.15s;
1150}
1151.mini-file-tab:hover {
1152  background: rgba(255,255,255,0.08);
1153}
1154.mini-file-tab.active {
1155  background: rgba(96,165,250,0.2);
1156  border-color: rgba(96,165,250,0.35);
1157  color: var(--text-primary);
1158}
1159.mini-explorer {
1160  border-right: 1px solid rgba(255,255,255,0.06);
1161  padding: 8px 0;
1162  background: rgba(0,0,0,0.08);
1163}
1164.mini-explorer-label {
1165  padding: 7px 14px;
1166  font-size: var(--font-caption-sm);
1167  color: var(--text-tertiary);
1168  text-transform: uppercase;
1169  letter-spacing: 0.5px;
1170  font-weight: 600;
1171}
1172.mini-file-item {
1173  padding: 7px 14px;
1174  font-size: var(--font-caption-sm);
1175  color: var(--text-secondary);
1176  cursor: pointer;
1177  display: flex;
1178  align-items: center;
1179  gap: 8px;
1180  transition: background 0.15s, color 0.15s;
1181  white-space: nowrap;
1182  overflow: hidden;
1183  text-overflow: ellipsis;
1184}
1185.mini-file-item:hover {
1186  background: rgba(255,255,255,0.04);
1187}
1188.mini-file-item.active {
1189  background: rgba(96,165,250,0.15);
1190  color: var(--text-primary);
1191}
1192.mini-file-item.view-more {
1193  color: var(--accent-secondary);
1194  font-style: italic;
1195  opacity: 0.8;
1196  margin-top: 4px;
1197  text-decoration: none;
1198}
1199.mini-file-item.view-more:hover {
1200  opacity: 1;
1201  background: rgba(96,165,250,0.10);
1202}
1203.mini-file-tab.view-more {
1204  color: var(--accent-secondary);
1205  font-style: italic;
1206  border-color: rgba(96,165,250,0.2);
1207  text-decoration: none;
1208}
1209.mini-file-tab.view-more:hover {
1210  background: rgba(96,165,250,0.10);
1211}
1212.mini-file-icon {
1213  opacity: 0.5;
1214}
1215.mini-code-panel {
1216  padding: 16px;
1217  overflow-y: auto;
1218  position: relative;
1219}
1220.mini-code-filename {
1221  display: flex;
1222  align-items: center;
1223  gap: 8px;
1224  margin-bottom: 12px;
1225  font-size: var(--font-caption-sm);
1226  color: var(--text-secondary);
1227}
1228.mini-code-panel .code-editor {
1229  height: 100%;
1230  background: transparent;
1231}
1232.mini-code-panel .code-editor-input {
1233  min-height: 0;
1234}
1235.mini-code-panel .code-editor-textarea,
1236.mini-code-panel .code-editor-highlight {
1237  padding: 0;
1238  padding-bottom: 40px;
1239  font-size: var(--font-caption-md);
1240  line-height: 1.6;
1241}
1242.mini-action-bar {
1243  display: flex;
1244  align-items: center;
1245  justify-content: flex-end;
1246  gap: 8px;
1247  padding: 8px 16px;
1248  border-bottom: 1px solid rgba(255,255,255,0.06);
1249  background: rgba(0,0,0,0.06);
1250  position: relative;
1251  flex-shrink: 0;
1252}
1253.mini-exec-btn {
1254  padding: 6px 14px;
1255  border: none;
1256  border-radius: 6px;
1257  color: white;
1258  font-size: 13px;
1259  font-weight: 500;
1260  cursor: pointer;
1261  transition: all 0.15s ease;
1262  display: flex;
1263  align-items: center;
1264  gap: 6px;
1265  font-family: inherit;
1266}
1267.mini-exec-btn:hover {
1268  transform: translateY(-1px);
1269  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
1270}
1271.mini-exec-btn:active { transform: translateY(0); }
1272.mini-exec-btn.compile {
1273  background: linear-gradient(135deg, #56b6c2 0%, #61afef 100%);
1274}
1275.mini-exec-btn.run {
1276  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1277}
1278.mini-terminal {
1279  border-top: 1px solid rgba(255,255,255,0.06);
1280  background: rgba(0,0,0,0.20);
1281  display: flex;
1282  flex-direction: column;
1283  overflow: hidden;
1284  position: relative;
1285}
1286.mini-terminal-head {
1287  display: flex;
1288  align-items: center;
1289  padding: 6px 16px;
1290  font-size: 11px;
1291  text-transform: uppercase;
1292  letter-spacing: 0.5px;
1293  color: var(--text-tertiary);
1294  font-weight: 600;
1295  border-bottom: 1px solid rgba(255,255,255,0.04);
1296  flex-shrink: 0;
1297}
1298.mini-terminal-body {
1299  flex: 1;
1300  min-height: 0;
1301  overflow-y: auto;
1302  padding: 8px 16px 13px;
1303  font-family: var(--font-mono);
1304  font-size: 12px;
1305  line-height: 1.5;
1306}
1307.mini-output-line {
1308  margin: 0;
1309  color: #4ade80;
1310  white-space: pre-wrap;
1311  font: inherit;
1312  line-height: inherit;
1313}
1314.mini-output-error {
1315  margin: 4px 0 0;
1316  color: #e06c75;
1317  white-space: pre-wrap;
1318  font: inherit;
1319  line-height: inherit;
1320  padding: 8px;
1321  background: rgba(224, 108, 117, 0.1);
1322  border-radius: 4px;
1323}
1324.mini-output-empty {
1325  color: var(--text-tertiary);
1326  font-style: italic;
1327}
1328.mini-output-loading {
1329  color: #667eea;
1330  animation: blink 1s step-end infinite;
1331}
1332.mini-term-output {
1333  margin: 0;
1334  color: #4ade80;
1335  white-space: pre-wrap;
1336  font: inherit;
1337  line-height: inherit;
1338}
1339.mini-compiled {
1340  border-top: 1px solid rgba(255,255,255,0.06);
1341  background: rgba(0,0,0,0.25);
1342  display: flex;
1343  flex-direction: column;
1344  overflow: hidden;
1345  position: relative;
1346}
1347.mini-compiled-head {
1348  display: flex;
1349  align-items: center;
1350  padding: 6px 16px;
1351  font-size: 11px;
1352  text-transform: uppercase;
1353  letter-spacing: 0.5px;
1354  color: var(--text-tertiary);
1355  font-weight: 600;
1356  border-bottom: 1px solid rgba(255,255,255,0.04);
1357  flex-shrink: 0;
1358}
1359.mini-compiled-body {
1360  flex: 1;
1361  min-height: 0;
1362  overflow-y: auto;
1363  padding: 8px 16px;
1364  font-family: var(--font-mono);
1365  font-size: 12px;
1366  line-height: 1.5;
1367  color: #e5c07b;
1368  white-space: pre-wrap;
1369  margin: 0;
1370}
1371.mini-terminal-resizer {
1372  height: 16px;
1373  background: transparent;
1374  cursor: row-resize;
1375  position: relative;
1376  flex-shrink: 0;
1377  z-index: 2;
1378}
1379.mini-terminal-resizer::after {
1380  content: "";
1381  position: absolute;
1382  left: 50%;
1383  top: 50%;
1384  transform: translate(-50%, -50%);
1385  width: 40px;
1386  height: 5px;
1387  border-radius: 3px;
1388  background: rgba(255,255,255,0.15);
1389  transition: background 0.15s ease;
1390}
1391.mini-terminal-resizer:hover::after,
1392.mini-terminal-resizer.active::after {
1393  background: rgba(96,165,250,0.6);
1394}
1395.mini-studio-cta {
1396  position: relative;
1397  padding: 12px 16px;
1398  border-top: 1px solid rgba(255,255,255,0.06);
1399  background: rgba(0,0,0,0.12);
1400  text-align: center;
1401  flex-shrink: 0;
1402}
1403.mini-cta-btn {
1404  display: inline-flex;
1405  align-items: center;
1406  gap: 8px;
1407  padding: 10px 24px;
1408  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
1409  border: none;
1410  border-radius: 8px;
1411  color: white;
1412  font-size: 14px;
1413  font-weight: 600;
1414  cursor: pointer;
1415  transition: all 0.18s ease;
1416  text-decoration: none;
1417  font-family: inherit;
1418}
1419.mini-cta-btn:hover {
1420  transform: translateY(-1px);
1421  box-shadow: 0 6px 20px rgba(59, 130, 246, 0.35);
1422}
1423
1424/* Mode Stories */
1425.mode-stories {
1426  display: grid;
1427  grid-template-columns: repeat(3, 1fr);
1428  gap: 18px;
1429}
1430.mode-story {
1431  border-radius: var(--radius-xl);
1432  border: 1px solid rgba(255,255,255,0.10);
1433  background: rgba(255,255,255,0.04);
1434  backdrop-filter: blur(18px);
1435  padding: 24px;
1436  transition: transform 0.18s ease, border-color 0.18s ease, background 0.18s ease;
1437  overflow: hidden;
1438}
1439.mode-story:hover {
1440  transform: translateY(-3px);
1441  border-color: rgba(167,139,250,0.28);
1442  background: rgba(255,255,255,0.06);
1443}
1444.mode-story-icon {
1445  width: 48px;
1446  height: 48px;
1447  border-radius: var(--radius-lg);
1448  display: flex;
1449  align-items: center;
1450  justify-content: center;
1451  font-size: 22px;
1452  font-weight: 700;
1453  margin-bottom: var(--spacing-md);
1454  border: 1px solid rgba(255,255,255,0.10);
1455}
1456.mode-story:nth-child(1) .mode-story-icon { background: rgba(96,165,250,0.15); color: #60a5fa; }
1457.mode-story:nth-child(2) .mode-story-icon { background: rgba(167,139,250,0.15); color: #a78bfa; }
1458.mode-story:nth-child(3) .mode-story-icon { background: rgba(34,197,94,0.15); color: #22c55e; }
1459.mode-story h3 {
1460  margin: 0 0 var(--spacing-md);
1461  font-size: var(--font-body-lg);
1462}
1463.mode-story-demo {
1464  border-radius: var(--radius-lg);
1465  background: rgba(0,0,0,0.3);
1466  padding: 12px;
1467  margin-bottom: var(--spacing-md);
1468  font-family: var(--font-mono);
1469  font-size: var(--font-caption-md);
1470  line-height: 1.6;
1471}
1472.mode-story-row {
1473  display: flex;
1474  gap: 8px;
1475  align-items: baseline;
1476}
1477.mode-story-label {
1478  color: var(--text-tertiary);
1479  font-size: var(--font-caption-sm);
1480  min-width: 54px;
1481  flex-shrink: 0;
1482}
1483.mode-story-value {
1484  color: var(--text-primary);
1485}
1486.mode-story-value.logic {
1487  color: var(--color-accent-purple);
1488}
1489.mode-story-value.success {
1490  color: var(--color-success);
1491}
1492.mode-story-arrow {
1493  text-align: center;
1494  color: var(--text-tertiary);
1495  padding: 4px 0;
1496  font-size: var(--font-caption-sm);
1497}
1498.mode-story > p {
1499  margin: 0;
1500  color: var(--text-secondary);
1501  font-size: var(--font-body-md);
1502  line-height: 1.6;
1503}
1504
1505/* Security Demo */
1506.security-demo {
1507  margin-top: var(--spacing-xl);
1508  border-radius: var(--radius-xl);
1509  border: 1px solid rgba(167,139,250,0.20);
1510  background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
1511  overflow: hidden;
1512  box-shadow:
1513    0 0 40px rgba(167,139,250,0.08),
1514    0 0 80px rgba(96,165,250,0.06),
1515    0 20px 60px rgba(0,0,0,0.4);
1516  position: relative;
1517}
1518.security-demo::before {
1519  content: "";
1520  position: absolute;
1521  inset: -1px;
1522  border-radius: var(--radius-xl);
1523  background: radial-gradient(400px 200px at 20% 0%, rgba(167,139,250,0.15), transparent 60%),
1524              radial-gradient(400px 200px at 80% 100%, rgba(96,165,250,0.12), transparent 60%);
1525  pointer-events: none;
1526}
1527.security-demo-head {
1528  position: relative;
1529  display: flex;
1530  align-items: center;
1531  justify-content: center;
1532  padding: 16px var(--spacing-lg);
1533  border-bottom: 1px solid rgba(255,255,255,0.08);
1534  background: rgba(0,0,0,0.12);
1535  font-size: var(--font-body-md);
1536  font-weight: 700;
1537  color: var(--text-primary);
1538  letter-spacing: -0.2px;
1539}
1540.security-demo-body {
1541  position: relative;
1542  display: grid;
1543  grid-template-columns: 1fr auto 1fr;
1544  align-items: stretch;
1545}
1546.security-demo-col {
1547  padding: 20px 24px;
1548}
1549.security-demo-col + .security-demo-col {
1550  border-left: 1px solid rgba(255,255,255,0.06);
1551}
1552.security-demo-arrow {
1553  display: flex;
1554  align-items: center;
1555  justify-content: center;
1556  padding: 0 16px;
1557  font-size: 28px;
1558  color: var(--color-accent-purple);
1559  border-left: 1px solid rgba(255,255,255,0.06);
1560  border-right: 1px solid rgba(255,255,255,0.06);
1561  background: rgba(0,0,0,0.06);
1562  text-shadow: 0 0 12px rgba(167,139,250,0.5);
1563}
1564.security-demo-label {
1565  display: inline-block;
1566  font-size: 11px;
1567  text-transform: uppercase;
1568  letter-spacing: 0.5px;
1569  font-weight: 600;
1570  color: #4ade80;
1571  margin-bottom: var(--spacing-sm);
1572  padding: 4px 10px;
1573  border: 1px solid rgba(74,222,128,0.3);
1574  border-radius: var(--radius-full);
1575  background: rgba(74,222,128,0.08);
1576}
1577
1578@media (max-width: 980px) {
1579  .hero-grid { grid-template-columns: 1fr; }
1580  .demo-body { grid-template-columns: 1fr; }
1581  .demo-col + .demo-col { border-left: none; border-top: 1px solid rgba(255,255,255,0.06); }
1582  .grid3 { grid-template-columns: 1fr; }
1583  .grid2 { grid-template-columns: 1fr; }
1584  .h-title { font-size: var(--font-display-lg); }
1585  .step-arrow { display: none; }
1586  .steps { flex-direction: column; }
1587  .mini-studio { height: 89vh !important; }
1588  .showcase-loading { min-height: 89vh; }
1589  .mini-studio-body { grid-template-columns: 1fr; }
1590  .mini-explorer { display: none; }
1591  .mini-file-tabs { display: flex; }
1592  .mini-terminal { max-height: 35vh !important; }
1593  .mini-compiled { max-height: 30vh !important; }
1594  .mode-stories { grid-template-columns: 1fr; }
1595  .security-demo-body { grid-template-columns: 1fr; }
1596  .security-demo-arrow { display: none; }
1597  .security-demo-col + .security-demo-col { border-left: none; border-top: 1px solid rgba(255,255,255,0.06); }
1598}
1599
1600@media (max-width: 768px) {
1601  .mini-studio { height: 89vh !important; }
1602  .mini-studio-head {
1603    justify-content: flex-end;
1604  }
1605  .mini-studio-head .win-dots {
1606    display: none;
1607  }
1608  .mini-exec-btn {
1609    padding: 10px 14px;
1610    min-height: 44px;
1611    font-size: 12px;
1612  }
1613  .mini-cta-btn {
1614    min-height: 44px;
1615    width: 100%;
1616    justify-content: center;
1617  }
1618  .mini-action-bar { padding: 8px 12px; }
1619}
1620
1621@media (max-width: 480px) {
1622  .mini-studio { height: 89vh !important; }
1623  .mini-exec-btn .btn-label { display: none; }
1624}
1625
1626@media (prefers-reduced-motion: reduce) {
1627  * { transition: none !important; animation: none !important; }
1628}
1629"#;
1630
1631#[component]
1632pub fn Landing() -> Element {
1633    let schemas = vec![
1634        organization_schema(),
1635        website_schema(),
1636        faq_schema(&[
1637            ("Is it really free?", "Yes — free for individuals, universities, and teams under 25 people. For commercial licensing, contact us."),
1638            ("Do I need to know logic already?", "No. Start in Learn. The system introduces concepts progressively and uses examples to teach scope, quantifiers, and structure."),
1639            ("Is this an AI that guesses?", "The goal is the opposite: to force explicit structure. When language is ambiguous, the tutor prompts clarifying questions."),
1640            ("Where do I begin?", "If you want speed, open Studio. If you want mastery, Start Learning and follow the lessons."),
1641            ("What is LOGOS written in?", "Rust. The entire transpiler, parser, and runtime are written in Rust for maximum performance and safety."),
1642            ("How fast is it?", "Native speed. LOGOS compiles to Rust, which then compiles via LLVM to optimized machine code. Zero interpreter overhead."),
1643        ]),
1644    ];
1645
1646    rsx! {
1647        PageHead {
1648            title: seo_pages::LANDING.title,
1649            description: seo_pages::LANDING.description,
1650            canonical_path: seo_pages::LANDING.canonical_path,
1651        }
1652        style { "{LANDING_STYLE}" }
1653        JsonLdMultiple { schemas }
1654
1655        div { class: "landing",
1656            div { class: "bg-orb orb1" }
1657            div { class: "bg-orb orb2" }
1658            div { class: "bg-orb orb3" }
1659
1660            MainNav { active: ActivePage::Other }
1661
1662            main { class: "container",
1663                section { class: "hero",
1664                    div { class: "hero-grid",
1665                        div {
1666                            div { class: "badge",
1667                                div { class: "dot" }
1668                                span { "Free for individuals • Commercial licenses available" }
1669                            }
1670
1671                            h1 { class: "h-title", "Debug Your Thoughts." }
1672
1673                            p { class: "h-sub",
1674                                "Write Code, Logic, and Math in plain English. LOGOS compiles your words into programs, proofs, and formal systems — no symbols required."
1675                            }
1676
1677                            div { class: "hero-ctas",
1678                                Link { to: Route::Learn {}, class: "btn btn-primary", "Start Learning" }
1679                                Link { to: Route::Studio { file: None }, class: "btn", "Open Studio" }
1680                                Link { to: Route::Pricing {}, class: "btn btn-ghost", "Contact Us" }
1681                            }
1682
1683                            p { class: "microcopy",
1684                                "Students, engineers, researchers, and attorneys — anyone who thinks for a living."
1685                            }
1686
1687                            div { class: "tech-stack",
1688                                span { class: "tech-badge rust",
1689                                    "Rust-Powered 🦀"
1690                                }
1691                                span { class: "tech-badge", "WASM Ready" }
1692                                span { class: "tech-badge", "Markdown Source" }
1693                                span { class: "tech-badge", "Proof-Checked" }
1694                            }
1695                        }
1696
1697                        SuspenseBoundary {
1698                            fallback: |_| rsx! { div { class: "showcase-loading" } },
1699                            LandingShowcase {}
1700                        }
1701                    }
1702                }
1703
1704                section { class: "section how-it-works section-center",
1705                    h2 { class: "section-title", "How it works" }
1706                    p { class: "section-sub",
1707                        "Three modes. One language: English."
1708                    }
1709
1710                    div { class: "mode-stories",
1711                        div { class: "mode-story",
1712                            div { class: "mode-story-icon", "λ" }
1713                            h3 { "Write a program" }
1714                            div { class: "mode-story-demo",
1715                                div { class: "mode-story-row",
1716                                    span { class: "mode-story-label", "Input" }
1717                                    span { class: "mode-story-value", "Let x be 10. Show x + 5." }
1718                                }
1719                                div { class: "mode-story-arrow", "↓" }
1720                                div { class: "mode-story-row",
1721                                    span { class: "mode-story-label", "Output" }
1722                                    span { class: "mode-story-value success", "15" }
1723                                }
1724                            }
1725                            p { "Type readable definitions. Get compiled programs — Rust under the hood, English on the surface." }
1726                        }
1727
1728                        div { class: "mode-story",
1729                            div { class: "mode-story-icon", "∀" }
1730                            h3 { "Formalize an argument" }
1731                            div { class: "mode-story-demo",
1732                                div { class: "mode-story-row",
1733                                    span { class: "mode-story-label", "Input" }
1734                                    span { class: "mode-story-value", "Every cat sleeps." }
1735                                }
1736                                div { class: "mode-story-arrow", "↓" }
1737                                div { class: "mode-story-row",
1738                                    span { class: "mode-story-label", "Output" }
1739                                    span { class: "mode-story-value logic", "∀x(Cat(x) → Sleep(x))" }
1740                                }
1741                            }
1742                            p { "Turn plain language into First-Order Logic. Every reading surfaced — no guessing." }
1743                        }
1744
1745                        div { class: "mode-story",
1746                            div { class: "mode-story-icon", "π" }
1747                            h3 { "Prove a theorem" }
1748                            div { class: "mode-story-demo",
1749                                div { class: "mode-story-row",
1750                                    span { class: "mode-story-label", "Input" }
1751                                    span { class: "mode-story-value", "Theorem: ∀n, n + 0 = n." }
1752                                }
1753                                div { class: "mode-story-arrow", "↓" }
1754                                div { class: "mode-story-row",
1755                                    span { class: "mode-story-label", "Output" }
1756                                    span { class: "mode-story-value success", "Proof: by induction. ✓" }
1757                                }
1758                            }
1759                            p { "Define types, state theorems, and prove them with automated tactics." }
1760                        }
1761                    }
1762                }
1763
1764                section { class: "section hello-world section-center hello-world-layout",
1765                    h2 { class: "section-title", "Hello World in LOGOS" }
1766
1767                    SuspenseBoundary {
1768                        fallback: |_| rsx! { div { class: "hello-loading" } },
1769                        LandingHelloWorld {}
1770                    }
1771                    div { class: "hello-pill-wrap",
1772                        p { class: "hello-note", "Compiles to a native binary via Rust. Zero runtime overhead." }
1773                    }
1774                    div { class: "hello-cta-wrap",
1775                        a { href: crate::ui::router::studio_file_url("examples/code/hello-world.logos"), class: "btn btn-primary",
1776                            "Open in Studio →"
1777                        }
1778                    }
1779                }
1780
1781                section { class: "section",
1782                    h2 { class: "section-title", "What you get" }
1783                    p { class: "section-sub",
1784                        "LOGICAFFEINE translates intuition into structure — so you can test it, teach it, or ship it."
1785                    }
1786
1787                    div { class: "grid3",
1788                        div { class: "card",
1789                            div { class: "icon-box",
1790                                Icon { variant: IconVariant::Lightning, size: IconSize::Large, color: "#00d4ff" }
1791                            }
1792                            h3 { "Instant Transpilation" }
1793                            p { "Type normal English. Get programs, logic, and math output in seconds — readable enough to learn from, strict enough to verify." }
1794                        }
1795                        div { class: "card",
1796                            div { class: "icon-box",
1797                                Icon { variant: IconVariant::Brain, size: IconSize::Large, color: "#818cf8" }
1798                            }
1799                            h3 { "Socratic Tutor" }
1800                            p { "When your statement is ambiguous, the tutor asks questions that force clarity instead of guessing." }
1801                        }
1802                        div { class: "card",
1803                            div { class: "icon-box",
1804                                Icon { variant: IconVariant::Document, size: IconSize::Large, color: "#22c55e" }
1805                            }
1806                            h3 { "Assumption Surfacing" }
1807                            p { "Reveal missing premises, hidden quantifiers, and scope mistakes — the usual sources of bad arguments." }
1808                        }
1809                        div { class: "card",
1810                            div { class: "icon-box",
1811                                Icon { variant: IconVariant::Beaker, size: IconSize::Large, color: "#fbbf24" }
1812                            }
1813                            h3 { "Consistency & Validity Checks" }
1814                            p { "Spot contradictions, invalid inferences, and rule collisions across Code, Logic, and Math modes — before they hit production or policy." }
1815                        }
1816                        div { class: "card",
1817                            div { class: "icon-box",
1818                                Icon { variant: IconVariant::Tools, size: IconSize::Large, color: "#ec4899" }
1819                            }
1820                            h3 { "Studio + Curriculum" }
1821                            p { "Explore freely in Studio, then build mastery in Learn with structured lessons and practice." }
1822                        }
1823                        div { class: "card",
1824                            div { class: "icon-box",
1825                                Icon { variant: IconVariant::Lock, size: IconSize::Large, color: "#8b5cf6" }
1826                            }
1827                            h3 { "Commercial-Ready" }
1828                            p { "Licensing options for teams and enterprises — with a path toward governance and controlled deployments." }
1829                        }
1830                    }
1831                }
1832
1833                section { class: "section section-center",
1834                    h2 { class: "section-title", "Security & Policies" }
1835                    p { class: "section-sub",
1836                        "Capability-based security with policy blocks. Define who can do what in plain English."
1837                    }
1838
1839                    div { class: "grid2",
1840                        div { class: "card",
1841                            div { class: "icon-box",
1842                                Icon { variant: IconVariant::Shield, size: IconSize::Large, color: "#60a5fa" }
1843                            }
1844                            h3 { "Policy Blocks" }
1845                            p { "Define security rules as readable policy sections. Who can access what — stated plainly." }
1846                        }
1847                        div { class: "card",
1848                            div { class: "icon-box",
1849                                Icon { variant: IconVariant::Lock, size: IconSize::Large, color: "#a78bfa" }
1850                            }
1851                            h3 { "Capabilities" }
1852                            p { "Role-based access control expressed in English. No annotation soup." }
1853                        }
1854                        div { class: "card",
1855                            div { class: "icon-box",
1856                                Icon { variant: IconVariant::Beaker, size: IconSize::Large, color: "#22c55e" }
1857                            }
1858                            h3 { "Check Guards" }
1859                            p { "Runtime guard checks that enforce your policies. \"Check that the user is admin.\"" }
1860                        }
1861                        div { class: "card",
1862                            div { class: "icon-box",
1863                                Icon { variant: IconVariant::Brain, size: IconSize::Large, color: "#fbbf24" }
1864                            }
1865                            h3 { "Predicates" }
1866                            p { "Define custom predicates: \"A User is admin if the user's role equals 'admin'.\"" }
1867                        }
1868                    }
1869
1870                    div { class: "security-demo",
1871                        div { class: "security-demo-head",
1872                            span { "Policy → Compiled Output" }
1873                        }
1874                        div { class: "security-demo-body",
1875                            div { class: "security-demo-col",
1876                                div { class: "security-demo-label", "LOGOS Policy" }
1877                                pre { class: "code",
1878"## Definition\nA User has:\n    a role: Text.\n\n## Policy\nA User is admin\n    if the user's role equals \"admin\".\n\n## Main\nLet u be a new User with role \"admin\".\nCheck that u is admin.\nShow \"Access granted\"." }
1879                            }
1880                            div { class: "security-demo-arrow", "→" }
1881                            div { class: "security-demo-col",
1882                                div { class: "security-demo-label", "Compiled Output" }
1883                                pre { class: "code",
1884"struct User {{\n    role: String,\n}}\n\nimpl User {{\n    fn is_admin(&self) -> bool {{\n        self.role == \"admin\"\n    }}\n}}\n\nfn main() {{\n    let u = User {{ role: \"admin\".into() }};\n    assert!(u.is_admin());\n    println!(\"Access granted\");\n}}" }
1885                            }
1886                        }
1887                    }
1888                }
1889
1890                section { class: "section", id: "for",
1891                    h2 { class: "section-title", style: "padding: 50px 0; font-size: var(--font-display-lg);",
1892                        "For people who want their reasoning to survive contact with reality."
1893                    }
1894
1895                    div { class: "grid3",
1896                        div { class: "card",
1897                            div { class: "icon-box",
1898                                Icon { variant: IconVariant::GraduationCap, size: IconSize::Large, color: "#00d4ff" }
1899                            }
1900                            h3 { "Students & Educators" }
1901                            p { "Teach formal reasoning with feedback that's immediate, concrete, and harder to game than multiple choice." }
1902                        }
1903                        div { class: "card",
1904                            div { class: "icon-box",
1905                                Icon { variant: IconVariant::Shield, size: IconSize::Large, color: "#818cf8" }
1906                            }
1907                            h3 { "Law, Policy, Compliance" }
1908                            p { "Translate policy language into verifiable rules. Reduce ambiguity. Make reviews faster and safer." }
1909                        }
1910                        div { class: "card",
1911                            div { class: "icon-box",
1912                                Icon { variant: IconVariant::Tools, size: IconSize::Large, color: "#22c55e" }
1913                            }
1914                            h3 { "Engineering & Research" }
1915                            p { "Specify systems, constraints, and invariants in a form you can test — without forcing everyone into formal syntax." }
1916                        }
1917                    }
1918                }
1919
1920                section { class: "section compare-section section-center",
1921                    h2 { class: "section-title", "How LOGOS Compares" }
1922                    p { class: "section-sub",
1923                        "A new approach to formal reasoning."
1924                    }
1925
1926                    div { class: "compare-table",
1927                        div { class: "compare-row header",
1928                            div { class: "compare-cell", "Feature" }
1929                            div { class: "compare-cell highlight", "LOGOS" }
1930                            div { class: "compare-cell", "Python" }
1931                            div { class: "compare-cell", "Lean 4" }
1932                            div { class: "compare-cell", "Rust" }
1933                            div { class: "compare-cell", "Elixir" }
1934                        }
1935                        div { class: "compare-row",
1936                            div { class: "compare-cell label", "Syntax" }
1937                            div { class: "compare-cell highlight", "English prose" }
1938                            div { class: "compare-cell", "Symbols" }
1939                            div { class: "compare-cell", "Lean DSL" }
1940                            div { class: "compare-cell", "Symbols" }
1941                            div { class: "compare-cell", "Symbols" }
1942                        }
1943                        div { class: "compare-row",
1944                            div { class: "compare-cell label", "File Format" }
1945                            div { class: "compare-cell highlight", "Markdown (.md)" }
1946                            div { class: "compare-cell", ".py" }
1947                            div { class: "compare-cell", ".lean" }
1948                            div { class: "compare-cell", ".rs" }
1949                            div { class: "compare-cell", ".ex" }
1950                        }
1951                        div { class: "compare-row",
1952                            div { class: "compare-cell label", "Performance" }
1953                            div { class: "compare-cell highlight", "Native (via Rust)" }
1954                            div { class: "compare-cell", "Interpreted" }
1955                            div { class: "compare-cell", "Native" }
1956                            div { class: "compare-cell", "Native" }
1957                            div { class: "compare-cell", "BEAM VM" }
1958                        }
1959                        div { class: "compare-row",
1960                            div { class: "compare-cell label", "Proofs" }
1961                            div { class: "compare-cell highlight", "Built-in" }
1962                            div { class: "compare-cell", "None" }
1963                            div { class: "compare-cell", "Required" }
1964                            div { class: "compare-cell", "Optional" }
1965                            div { class: "compare-cell", "None" }
1966                        }
1967                        div { class: "compare-row",
1968                            div { class: "compare-cell label", "Memory" }
1969                            div { class: "compare-cell highlight", "Ownership (English)" }
1970                            div { class: "compare-cell", "GC" }
1971                            div { class: "compare-cell", "GC" }
1972                            div { class: "compare-cell", "Ownership" }
1973                            div { class: "compare-cell", "GC" }
1974                        }
1975                    }
1976                }
1977
1978                section { class: "section", id: "faq",
1979                    h2 { class: "section-title", "FAQ" }
1980                    p { class: "section-sub",
1981                        "Common questions about LOGICAFFEINE."
1982                    }
1983
1984                    div { class: "grid2",
1985                        div { class: "faq-item",
1986                            div { class: "faq-q", "Is it really free?" }
1987                            div { class: "faq-a", "Yes — free for individuals, universities, and teams under 25 people. For commercial licensing, contact us." }
1988                        }
1989                        div { class: "faq-item",
1990                            div { class: "faq-q", "Do I need to know logic already?" }
1991                            div { class: "faq-a", "No. Start in Learn. The system introduces concepts progressively and uses examples to teach scope, quantifiers, and structure." }
1992                        }
1993                        div { class: "faq-item",
1994                            div { class: "faq-q", "Is this an AI that \"guesses\"?" }
1995                            div { class: "faq-a", "The goal is the opposite: to force explicit structure. When language is ambiguous, the tutor prompts clarifying questions." }
1996                        }
1997                        div { class: "faq-item",
1998                            div { class: "faq-q", "Where do I begin?" }
1999                            div { class: "faq-a", "If you want speed, open Studio. If you want mastery, Start Learning and follow the lessons." }
2000                        }
2001                        div { class: "faq-item",
2002                            div { class: "faq-q", "What is LOGOS written in?" }
2003                            div { class: "faq-a", "Rust. The entire transpiler, parser, and runtime are written in Rust for maximum performance and safety." }
2004                        }
2005                        div { class: "faq-item",
2006                            div { class: "faq-q", "How fast is it?" }
2007                            div { class: "faq-a", "Native speed. LOGOS compiles to Rust, which then compiles via LLVM to optimized machine code. Zero interpreter overhead." }
2008                        }
2009                    }
2010                }
2011
2012                section {
2013                    class: "section",
2014                    style: "padding-bottom: 100px;",
2015                    div {
2016                        class: "card",
2017                        style: "padding: 32px; overflow: visible;",
2018                        h2 { class: "section-title", "Make your reasoning impossible to ignore." }
2019                        p {
2020                            class: "section-sub",
2021                            style: "margin-bottom: 20px;",
2022                            "Start with the Curriculum, or explore any mode in the Studio. Code, Logic, Math — your call."
2023                        }
2024                        div { class: "hero-ctas",
2025                            Link { to: Route::Learn {}, class: "btn btn-primary", "Start Learning" }
2026                            Link { to: Route::Pricing {}, class: "btn btn-ghost", "Contact Us" }
2027                        }
2028                    }
2029                }
2030
2031                Footer {}
2032            }
2033        }
2034    }
2035}
2036
2037// `lazy`: with the `split` feature + dx `--wasm-split`, the interactive demo body
2038// (and the LOGOS engine — logicaffeine_compile/logicaffeine_kernel — that only it
2039// references) moves into the lazily-fetched chunk, keeping the eager core engine-free.
2040#[component(lazy)]
2041fn LandingShowcase() -> Element {
2042    let mut demo_mode = use_signal(|| StudioMode::Code);
2043    let mut active_index = use_signal(|| 0usize);
2044    let mut cycling_paused = use_signal(|| false);
2045    let mut timer_started = use_signal(|| false);
2046    let mut terminal_height = use_signal(|| 135.0f64);
2047    let mut resizing_terminal = use_signal(|| false);
2048    let mut compiled_height = use_signal(|| 140.0f64);
2049    let mut show_compiled = use_signal(|| false);
2050    let mut resizing_compiled = use_signal(|| false);
2051    let mut code_content = use_signal(|| String::new());
2052    let mut output_lines = use_signal(|| Vec::<String>::new());
2053    let mut output_error = use_signal(|| Option::<String>::None);
2054    let mut compiled_output = use_signal(|| String::new());
2055    let mut is_running = use_signal(|| false);
2056
2057    use_effect(move || {
2058        let mode = *demo_mode.read();
2059        let idx = *active_index.read();
2060        let examples = examples_for_mode(mode);
2061        let clamped = idx.min(examples.len().saturating_sub(1));
2062        let ex = &examples[clamped];
2063        let content = ex.content.to_string();
2064        code_content.set(content.clone());
2065        output_error.set(None);
2066        compiled_output.set(ex.compiled.to_string());
2067
2068        match mode {
2069            StudioMode::Code => {
2070                output_lines.set(Vec::new());
2071                spawn(async move {
2072                    let result = interpret_for_ui(&content).await;
2073                    output_lines.set(result.lines);
2074                    output_error.set(result.error);
2075                });
2076            }
2077            StudioMode::Logic | StudioMode::Hardware => {
2078                let mut lines: Vec<String> = Vec::new();
2079
2080                if content.contains("## Theorem:") {
2081                    for line in content.lines() {
2082                        let trimmed = line.trim();
2083                        if let Some(sentence) = trimmed.strip_prefix("Given:") {
2084                            let fol = compile_for_ui(sentence.trim());
2085                            if let Some(logic) = fol.logic {
2086                                lines.push(logic);
2087                            }
2088                        } else if let Some(sentence) = trimmed.strip_prefix("Prove:") {
2089                            let fol = compile_for_ui(sentence.trim());
2090                            if let Some(logic) = fol.logic {
2091                                lines.push(format!("Goal: {}", logic));
2092                            }
2093                        }
2094                    }
2095
2096                    let theorem_result = compile_theorem_for_ui(&content);
2097                    if let Some(ref err) = theorem_result.error {
2098                        output_error.set(Some(err.clone()));
2099                    } else {
2100                        lines.push(String::new());
2101                        if theorem_result.derivation.is_some() {
2102                            lines.push(format!("Theorem: {} ✓", theorem_result.name));
2103                        } else {
2104                            lines.push(format!("Theorem: {} — not proved", theorem_result.name));
2105                        }
2106                    }
2107                } else {
2108                    let result = compile_for_ui(&content);
2109                    if let Some(logic) = result.logic {
2110                        for line in logic.lines() {
2111                            lines.push(line.to_string());
2112                        }
2113                    }
2114                    if let Some(ref err) = result.error {
2115                        output_error.set(Some(err.clone()));
2116                    }
2117                }
2118
2119                output_lines.set(lines);
2120            }
2121            StudioMode::Math => {
2122                let (lines, err) = execute_math_code(&content);
2123                output_lines.set(lines);
2124                output_error.set(err);
2125            }
2126        }
2127    });
2128
2129    use_effect(move || {
2130        if *timer_started.read() { return; }
2131        timer_started.set(true);
2132        #[cfg(target_arch = "wasm32")]
2133        spawn(async move {
2134            loop {
2135                gloo_timers::future::TimeoutFuture::new(7_000).await;
2136                if !*cycling_paused.read() {
2137                    let mode = *demo_mode.read();
2138                    let count = examples_for_mode(mode).len();
2139                    let next = (*active_index.read() + 1) % count;
2140                    active_index.set(next);
2141                }
2142            }
2143        });
2144    });
2145
2146    rsx! {
2147        div {
2148            class: "mini-studio",
2149            id: "product",
2150            style: if *resizing_terminal.read() || *resizing_compiled.read() { "user-select: none;" } else { "" },
2151            onmouseenter: move |_| { cycling_paused.set(true); },
2152            onmouseleave: move |_| {
2153                cycling_paused.set(false);
2154                resizing_terminal.set(false);
2155                resizing_compiled.set(false);
2156            },
2157            onmousemove: move |evt| {
2158                let window = web_sys::window().unwrap();
2159                let document = window.document().unwrap();
2160                let cta_height: f64 = 45.0;
2161                if *resizing_terminal.read() {
2162                    if let Some(el) = document.get_element_by_id("product") {
2163                        let rect = el.get_bounding_client_rect();
2164                        let coords = evt.data().client_coordinates();
2165                        let client_y: f64 = coords.y;
2166                        let below = cta_height
2167                            + if *show_compiled.read() { *compiled_height.read() + 6.0 } else { 0.0 };
2168                        let new_height = rect.bottom() - client_y - below;
2169                        terminal_height.set(new_height.clamp(60.0, 300.0));
2170                    }
2171                } else if *resizing_compiled.read() {
2172                    if let Some(el) = document.get_element_by_id("product") {
2173                        let rect = el.get_bounding_client_rect();
2174                        let coords = evt.data().client_coordinates();
2175                        let client_y: f64 = coords.y;
2176                        let new_height = rect.bottom() - client_y - cta_height;
2177                        let max_compiled = rect.height() - *terminal_height.read() - cta_height - 6.0 - 120.0;
2178                        compiled_height.set(new_height.clamp(60.0, max_compiled.max(60.0)));
2179                    }
2180                }
2181            },
2182            onmouseup: move |_| {
2183                resizing_terminal.set(false);
2184                resizing_compiled.set(false);
2185            },
2186            ontouchmove: move |evt| {
2187                let window = web_sys::window().unwrap();
2188                let document = window.document().unwrap();
2189                let cta_height: f64 = 45.0;
2190                if *resizing_terminal.read() || *resizing_compiled.read() {
2191                    evt.prevent_default();
2192                    let touches = evt.data().touches();
2193                    if let Some(touch) = touches.first() {
2194                        if let Some(el) = document.get_element_by_id("product") {
2195                            let rect = el.get_bounding_client_rect();
2196                            let coords = touch.client_coordinates();
2197                            let client_y: f64 = coords.y;
2198                            if *resizing_terminal.read() {
2199                                let below = cta_height
2200                                    + if *show_compiled.read() { *compiled_height.read() + 6.0 } else { 0.0 };
2201                                let new_height = rect.bottom() - client_y - below;
2202                                terminal_height.set(new_height.clamp(60.0, 300.0));
2203                            } else {
2204                                let new_height = rect.bottom() - client_y - cta_height;
2205                                let max_compiled = rect.height() - *terminal_height.read() - cta_height - 6.0 - 120.0;
2206                                compiled_height.set(new_height.clamp(60.0, max_compiled.max(60.0)));
2207                            }
2208                        }
2209                    }
2210                }
2211            },
2212            ontouchend: move |_| {
2213                resizing_terminal.set(false);
2214                resizing_compiled.set(false);
2215            },
2216
2217            div { class: "mini-studio-head",
2218                div { class: "win-dots",
2219                    div { class: "wdot wr" }
2220                    div { class: "wdot wy" }
2221                    div { class: "wdot wg" }
2222                }
2223                div { class: "mini-mode-toggle",
2224                    button {
2225                        class: if *demo_mode.read() == StudioMode::Code { "mini-toggle-btn active" } else { "mini-toggle-btn" },
2226                        onclick: move |_| {
2227                            demo_mode.set(StudioMode::Code);
2228                            active_index.set(0);
2229                        },
2230                        span { "λ" }
2231                        span { class: "mini-toggle-label", "Code" }
2232                    }
2233                    button {
2234                        class: if *demo_mode.read() == StudioMode::Logic { "mini-toggle-btn active" } else { "mini-toggle-btn" },
2235                        onclick: move |_| {
2236                            demo_mode.set(StudioMode::Logic);
2237                            active_index.set(0);
2238                            show_compiled.set(false);
2239                        },
2240                        span { "∀" }
2241                        span { class: "mini-toggle-label", "Logic" }
2242                    }
2243                    button {
2244                        class: if *demo_mode.read() == StudioMode::Math { "mini-toggle-btn active" } else { "mini-toggle-btn" },
2245                        onclick: move |_| {
2246                            demo_mode.set(StudioMode::Math);
2247                            active_index.set(0);
2248                            show_compiled.set(false);
2249                        },
2250                        span { "π" }
2251                        span { class: "mini-toggle-label", "Math" }
2252                    }
2253                }
2254            }
2255
2256            div { class: "mini-action-bar",
2257                if *demo_mode.read() == StudioMode::Code {
2258                    button {
2259                        class: "mini-exec-btn compile",
2260                        onclick: move |_| {
2261                            let code = code_content.read().clone();
2262
2263                            match generate_rust_code(&code) {
2264                                Ok(rust) => compiled_output.set(rust),
2265                                Err(e) => compiled_output.set(format!("// Compile error: {:?}", e)),
2266                            }
2267
2268                            let current = *show_compiled.read();
2269                            if !current {
2270                                show_compiled.set(true);
2271                            }
2272                        },
2273                        "🦀"
2274                        span { class: "btn-label", "Compile to Rust" }
2275                    }
2276                }
2277                button {
2278                    class: "mini-exec-btn run",
2279                    onclick: move |_| {
2280                        let code = code_content.read().clone();
2281                        let mode = *demo_mode.read();
2282                        is_running.set(true);
2283                        output_lines.set(Vec::new());
2284                        output_error.set(None);
2285
2286                        match mode {
2287                            StudioMode::Code => {
2288                                spawn(async move {
2289                                    let result = interpret_for_ui(&code).await;
2290                                    output_lines.set(result.lines);
2291                                    output_error.set(result.error);
2292                                    is_running.set(false);
2293                                });
2294                            }
2295                            StudioMode::Logic | StudioMode::Hardware => {
2296                                let mut lines: Vec<String> = Vec::new();
2297
2298                                if code.contains("## Theorem:") {
2299                                    // FOL transpilation: compile each premise sentence individually
2300                                    for line in code.lines() {
2301                                        let trimmed = line.trim();
2302                                        if let Some(sentence) = trimmed.strip_prefix("Given:") {
2303                                            let sentence = sentence.trim();
2304                                            let fol = compile_for_ui(sentence);
2305                                            if let Some(logic) = fol.logic {
2306                                                lines.push(logic);
2307                                            }
2308                                        } else if let Some(sentence) = trimmed.strip_prefix("Prove:") {
2309                                            let sentence = sentence.trim();
2310                                            let fol = compile_for_ui(sentence);
2311                                            if let Some(logic) = fol.logic {
2312                                                lines.push(format!("Goal: {}", logic));
2313                                            }
2314                                        }
2315                                    }
2316
2317                                    // Proof verification
2318                                    let theorem_result = compile_theorem_for_ui(&code);
2319                                    if let Some(ref err) = theorem_result.error {
2320                                        output_error.set(Some(err.clone()));
2321                                    } else {
2322                                        lines.push(String::new());
2323                                        let proved = theorem_result.derivation.is_some();
2324                                        if proved {
2325                                            lines.push(format!("Theorem: {} ✓", theorem_result.name));
2326                                        } else {
2327                                            lines.push(format!("Theorem: {} — not proved", theorem_result.name));
2328                                        }
2329                                    }
2330                                } else {
2331                                    let result = compile_for_ui(&code);
2332                                    if let Some(logic) = result.logic {
2333                                        for line in logic.lines() {
2334                                            lines.push(line.to_string());
2335                                        }
2336                                    }
2337                                    if let Some(ref err) = result.error {
2338                                        output_error.set(Some(err.clone()));
2339                                    }
2340                                }
2341
2342                                output_lines.set(lines);
2343                                is_running.set(false);
2344                            }
2345                            StudioMode::Math => {
2346                                let (lines, err) = execute_math_code(&code);
2347                                output_lines.set(lines);
2348                                output_error.set(err);
2349                                is_running.set(false);
2350                            }
2351                        }
2352                    },
2353                    "▶"
2354                    span { class: "btn-label",
2355                        if *demo_mode.read() == StudioMode::Code { "Run" } else { "Execute" }
2356                    }
2357                }
2358            }
2359
2360            div { class: "mini-file-tabs",
2361                for i in 0..examples_for_mode(*demo_mode.read()).len() {
2362                    button {
2363                        key: "{i}",
2364                        class: if *active_index.read() == i { "mini-file-tab active" } else { "mini-file-tab" },
2365                        onclick: move |_| {
2366                            active_index.set(i);
2367                            cycling_paused.set(true);
2368                        },
2369                        "{examples_for_mode(*demo_mode.read())[i].filename}"
2370                    }
2371                }
2372                a {
2373                    class: "mini-file-tab view-more",
2374                    href: "/studio",
2375                    "View more..."
2376                }
2377            }
2378
2379            div { class: "mini-studio-body",
2380                div { class: "mini-explorer",
2381                    div { class: "mini-explorer-label", "FILES" }
2382                    for i in 0..examples_for_mode(*demo_mode.read()).len() {
2383                        div {
2384                            key: "{i}",
2385                            class: if *active_index.read() == i { "mini-file-item active" } else { "mini-file-item" },
2386                            onclick: move |_| {
2387                                active_index.set(i);
2388                                cycling_paused.set(true);
2389                            },
2390                            span { class: "mini-file-icon", "●" }
2391                            span { "{examples_for_mode(*demo_mode.read())[i].filename}" }
2392                        }
2393                    }
2394                    a {
2395                        class: "mini-file-item view-more",
2396                        href: "/studio",
2397                        "View more..."
2398                    }
2399                }
2400                div { class: "mini-code-panel",
2401                    {
2402                        let mode = *demo_mode.read();
2403                        let examples = examples_for_mode(mode);
2404                        let idx = (*active_index.read()).min(examples.len().saturating_sub(1));
2405                        let ex = &examples[idx];
2406                        rsx! {
2407                            div { class: "mini-code-filename",
2408                                span { "{ex.filename}" }
2409                                span { "  {ex.icon}" }
2410                            }
2411                            CodeEditor {
2412                                value: code_content.read().clone(),
2413                                on_change: move |v: String| code_content.set(v),
2414                                language: match mode {
2415                                    StudioMode::Code => Language::Logos,
2416                                    StudioMode::Logic | StudioMode::Hardware => Language::Logos,
2417                                    StudioMode::Math => Language::Vernacular,
2418                                },
2419                                placeholder: "Enter code...".to_string(),
2420                            }
2421                        }
2422                    }
2423                }
2424            }
2425
2426            div {
2427                class: if *resizing_terminal.read() { "mini-terminal-resizer active" } else { "mini-terminal-resizer" },
2428                onmousedown: move |e| {
2429                    e.prevent_default();
2430                    resizing_terminal.set(true);
2431                },
2432                ontouchstart: move |e| {
2433                    e.prevent_default();
2434                    resizing_terminal.set(true);
2435                },
2436            }
2437
2438            div { class: "mini-terminal", style: "height: {terminal_height}px;",
2439                div { class: "mini-terminal-head", "OUTPUT" }
2440                div { class: "mini-terminal-body",
2441                    if *is_running.read() {
2442                        div { class: "mini-output-loading", "Running..." }
2443                    }
2444                    {
2445                        let lines = output_lines.read().clone();
2446                        let error = output_error.read().clone();
2447                        rsx! {
2448                            for (i, line) in lines.iter().enumerate() {
2449                                pre { key: "{i}", class: "mini-output-line", "{line}" }
2450                            }
2451                            if let Some(ref err) = error {
2452                                pre { class: "mini-output-error", "{err}" }
2453                            }
2454                            if lines.is_empty() && error.is_none() && !*is_running.read() {
2455                                div { class: "mini-output-empty", "Click Run to see output" }
2456                            }
2457                        }
2458                    }
2459                }
2460            }
2461
2462            if *show_compiled.read() {
2463                div {
2464                    class: if *resizing_compiled.read() { "mini-terminal-resizer active" } else { "mini-terminal-resizer" },
2465                    onmousedown: move |e| {
2466                        e.prevent_default();
2467                        resizing_compiled.set(true);
2468                    },
2469                    ontouchstart: move |e| {
2470                        e.prevent_default();
2471                        resizing_compiled.set(true);
2472                    },
2473                }
2474                div { class: "mini-compiled", style: "height: {compiled_height}px;",
2475                    div { class: "mini-compiled-head", "COMPILED RUST" }
2476                    pre { class: "mini-compiled-body", "{compiled_output}" }
2477                }
2478            }
2479
2480            div { class: "mini-studio-cta",
2481                {
2482                    let mode = *demo_mode.read();
2483                    let examples = examples_for_mode(mode);
2484                    let idx = (*active_index.read()).min(examples.len().saturating_sub(1));
2485                    let studio_url = crate::ui::router::studio_file_url(examples[idx].studio_path);
2486                    rsx! {
2487                        a { href: "{studio_url}", class: "mini-cta-btn",
2488                            "Try it in the Studio →"
2489                        }
2490                    }
2491                }
2492            }
2493        }
2494    }
2495}
2496
2497// `lazy`: keeps the hello-world editor's interpreter dependency out of the eager core.
2498#[component(lazy)]
2499fn LandingHelloWorld() -> Element {
2500    let mut hello_code = use_signal(|| CODE_DEMO_EXAMPLES[0].content.to_string());
2501    let mut hello_output = use_signal(|| CODE_DEMO_EXAMPLES[0].output.lines().map(|l| l.to_string()).collect::<Vec<_>>());
2502    let mut hello_error = use_signal(|| Option::<String>::None);
2503    let mut hello_running = use_signal(|| false);
2504
2505    rsx! {
2506        div { class: "hello-editor",
2507            div { class: "hello-editor-head",
2508                span { class: "hello-filename", "hello-world.logos" }
2509                button {
2510                    class: "hello-run-btn",
2511                    disabled: *hello_running.read(),
2512                    onclick: move |_| {
2513                        let code = hello_code.read().clone();
2514                        hello_running.set(true);
2515                        hello_output.set(Vec::new());
2516                        hello_error.set(None);
2517                        spawn(async move {
2518                            let result = interpret_for_ui(&code).await;
2519                            hello_output.set(result.lines);
2520                            hello_error.set(result.error);
2521                            hello_running.set(false);
2522                        });
2523                    },
2524                    if *hello_running.read() { "Running..." } else { "▶ Run" }
2525                }
2526            }
2527            div { class: "hello-editor-body",
2528                div { class: "hello-editor-left",
2529                    CodeEditor {
2530                        value: hello_code.read().clone(),
2531                        on_change: move |v: String| hello_code.set(v),
2532                        language: Language::Logos,
2533                        placeholder: "Enter code...".to_string(),
2534                    }
2535                }
2536                div { class: "hello-editor-right",
2537                    div { class: "hello-output-head", "Output" }
2538                    div { class: "hello-output-body",
2539                        if *hello_running.read() {
2540                            div { class: "hello-output-loading", "Running..." }
2541                        }
2542                        {
2543                            let lines = hello_output.read().clone();
2544                            let error = hello_error.read().clone();
2545                            rsx! {
2546                                for (i, line) in lines.iter().enumerate() {
2547                                    pre { key: "{i}", class: "hello-output-line", "{line}" }
2548                                }
2549                                if let Some(ref err) = error {
2550                                    pre { class: "hello-output-error", "{err}" }
2551                                }
2552                                if lines.is_empty() && error.is_none() && !*hello_running.read() {
2553                                    div { class: "hello-output-empty", "Click Run to see output" }
2554                                }
2555                            }
2556                        }
2557                    }
2558                }
2559            }
2560        }
2561    }
2562}