const features = [_]Feature{
    .{ .icon_fn = icons.Lightning, .title = "Fast Performance", .description = "Significantly faster at SSR than many other frameworks. Optimized for speed and low latency." },
    // .{ .icon_fn = icons.Shield, .title = "Deterministic Safety", .description = "Built on Zig's safety features. Zero undefined behavior at runtime. Predictable and reliable." },
    .{ .icon_fn = icons.Code, .title = "Familiar Syntax", .description = "Familiar JSX-like syntax, or plain HTML-style markup, with full access to Zig's control flow." },
    // .{ .icon_fn = icons.Globe, .title = "Edge First", .description = "Native support for WASI and Edge runtimes. Deploy to Cloudflare Workers or Vercel Edge with zero config." },
    // .{ .icon_fn = icons.Package, .title = "Zero Dependencies", .description = "Self-contained framework. No node_modules, no external runtimes. Just one small binary." },
    .{ .icon_fn = icons.Folder, .title = "File System Routing", .description = "Just put files in folders to create routes. Simple and intuitive structure for any scale." },
    .{ .icon_fn = icons.Server, .title = "API Routes", .description = "Create API endpoints by adding route.zig files to your project. Native Zig performance." },
    .{ .icon_fn = icons.Monitor, .title = "Hybrid Rendering", .description = "Optional client-side rendering for interactive experiences when you need it. SSR by default." },
    .{ .icon_fn = icons.Flow, .title = "Control Flow", .description = "if/else, for/while, and switch all work as expected. It's just Zig syntax." },
    .{ .icon_fn = icons.Wrench, .title = "Developer Tooling", .description = "CLI, hot reload, and editor extensions for the best development experience." },
    .{ .icon_fn = icons.Rocket, .title = "Deploy Anywhere", .description = "Standalone binaries, Cloudflare, Vercel (soon), or any WASI-compatible host. Build once, run anywhere." },
    .{ .icon_fn = icons.Layers, .title = "Predictable Memory", .description = "Explicit memory management. No GC pauses, no hidden allocations. Total control over your app's footprint." },
 };

const deployments = [_]Deployment{
    .{ .icon_fn = icons.Terminal, .title = "Standalone", .description = "Deploy as a self-contained binary on Linux, macOS, or Windows. Statically linked with zero runtime dependencies." },
    .{ .icon_fn = icons.Globe, .title = "Edge Anywhere", .description = "Deploy to the edge via WASI. Native support for Cloudflare and Vercel (soon)." },
    .{ .icon_fn = icons.Layers, .title = "Static", .description = "Generate a statically pre-rendered site at build time. Deploy to GitHub Pages, Netlify, S3, or any CDN." },
    .{ .icon_fn = icons.Package, .title = "Cross-Platform", .description = "Build for any target from any host. Easily cross-compile optimized binaries for x86_64, aarch64, and more." },
};

const benchmark_cwv_rows = [_]BenchmarkRow{
    .{ .label = "Ziex", .value = 98, .display = "98%", .url = "" },
    .{ .label = "Next.js", .value = 44, .display = "44%", .url = "https://nextjs.org" },
    .{ .label = "Nuxt", .value = 42, .display = "42%", .url = "https://nuxt.com" },
    .{ .label = "Leptos", .value = 27, .display = "27%", .url = "https://leptos.dev" },
};

// Import benchmark data from auto-generated file
const bench_data = @import("bench.zon");
const bench_len = @typeInfo(@TypeOf(bench_data)).@"struct".fields.len;

// Helper function to format large numbers (e.g., 25153 -> "25k")
fn formatLargeNumber(n: f64) []const u8 {
    if (n >= 1000) {
        const k = n / 1000;
        if (k >= 10) {
            return std.fmt.comptimePrint("{d}k", .{@as(u32, @intFromFloat(k))});
        } else {
            return std.fmt.comptimePrint("{d:.1}k", .{k});
        }
    }
    return std.fmt.comptimePrint("{d}", .{@as(u32, @intFromFloat(n))});
}

// Helper function to format memory with 1 decimal place (e.g., 9.8 MB)
fn formatMemory(mb: f64) []const u8 {
    return std.fmt.comptimePrint("{d:.1} MB", .{mb});
}

// Helper function to format requests per second with comma separator
fn formatRequests(n: f64) []const u8 {
    const int_val = @as(u32, @intFromFloat(n));
    if (int_val >= 10000) {
        const thousands = int_val / 1000;
        const remainder = int_val % 1000;
        return std.fmt.comptimePrint("{d},{d:0>3}", .{ thousands, remainder });
    }
    if (int_val >= 1000) {
        const thousands = int_val / 1000;
        const remainder = int_val % 1000;
        return std.fmt.comptimePrint("{d},{d}", .{ thousands, remainder });
    }
    return std.fmt.comptimePrint("{d}", .{int_val});
}

// Helper function to format latency in milliseconds
fn formatLatency(ms: f64) []const u8 {
    return std.fmt.comptimePrint("{d:.2} ms", .{ms});
}

// Helper function to format build time in seconds
fn formatBuildTime(s: f64) []const u8 {
    const int_s = @as(u32, @intFromFloat(s));
    if (int_s >= 60) {
        const mins = int_s / 60;
        const secs = int_s % 60;
        return std.fmt.comptimePrint("{d}m {d}s", .{ mins, secs });
    }
    return std.fmt.comptimePrint("{d}s", .{int_s});
}

// Helper function to format image size (e.g., "18 MB", "1.0 GB")
fn formatImageSize(mb: f64) []const u8 {
    if (mb >= 1000) {
        const gb = mb / 1000;
        return std.fmt.comptimePrint("{d:.1} GB", .{gb});
    }
    return std.fmt.comptimePrint("{d} MB", .{@as(u32, @intFromFloat(mb))});
}

// Helper function to format cold start time in milliseconds
fn formatColdStart(ms: f64) []const u8 {
    return std.fmt.comptimePrint("{d} ms", .{@as(u32, @intFromFloat(ms))});
}

// Helper function to format CPU peak percentage
fn formatCpuPeak(pct: f64) []const u8 {
    return std.fmt.comptimePrint("{d:.1}%", .{pct});
}

// Helper function to format binary size in MB
fn formatBinarySize(mb: f64) []const u8 {
    if (mb == 0) return "N/A";
    return std.fmt.comptimePrint("{d:.1} MB", .{mb});
}

// Map framework id to its website URL
fn getFrameworkUrl(comptime id: []const u8) []const u8 {
    if (std.mem.eql(u8, id, "jetzig")) return "https://jetzig.dev";
    if (std.mem.eql(u8, id, "leptos")) return "https://leptos.dev";
    if (std.mem.eql(u8, id, "solidjs")) return "https://start.solidjs.com";
    if (std.mem.eql(u8, id, "dioxus")) return "https://dioxuslabs.com";
    if (std.mem.eql(u8, id, "nextjs")) return "https://nextjs.org";
    return "";
}

fn buildSsrRows() [bench_len]BenchmarkRow {
    @setEvalBranchQuota(10000);
    var rows: [bench_len]BenchmarkRow = undefined;
    const fields = @typeInfo(@TypeOf(bench_data)).@"struct".fields;
    inline for (fields, 0..) |field, i| {
        const d = @field(bench_data, field.name);
        rows[i] = .{
            .label = d.label,
            .value = d.requests_per_sec,
            .display = formatLargeNumber(d.requests_per_sec),
            .url = getFrameworkUrl(d.id),
            .tooltip_metrics = &[_]TooltipMetric{
                .{ .label = "Framework", .value = d.label },
                .{ .label = "Requests/sec", .value = formatRequests(d.requests_per_sec) },
                .{ .label = "P50 Latency", .value = formatLatency(d.p50_latency_ms) },
                .{ .label = "P99 Latency", .value = formatLatency(d.p99_latency_ms) },
            },
        };
    }
    // Sort rows descending by value (higher is better)
    std.sort.insertion(BenchmarkRow, &rows, {}, struct {
        fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool {
            return a.value > b.value;
        }
    }.lessThan);
    return rows;
}

fn buildMemoryRows() [bench_len]BenchmarkRow {
    @setEvalBranchQuota(10000);
    var rows: [bench_len]BenchmarkRow = undefined;
    const fields = @typeInfo(@TypeOf(bench_data)).@"struct".fields;
    inline for (fields, 0..) |field, i| {
        const d = @field(bench_data, field.name);
        rows[i] = .{
            .label = d.label,
            .value = -d.peak_memory_mb,
            .display = formatMemory(d.peak_memory_mb),
            .url = getFrameworkUrl(d.id),
            .tooltip_metrics = &[_]TooltipMetric{
                .{ .label = "Framework", .value = d.label },
                .{ .label = "Idle Memory", .value = formatMemory(d.idle_memory_mb) },
                .{ .label = "Peak Memory", .value = formatMemory(d.peak_memory_mb) },
            },
        };
    }
    // Sort rows ascending by peak memory (lower is better, so -value is higher is better)
    std.sort.insertion(BenchmarkRow, &rows, {}, struct {
        fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool {
            return a.value > b.value;
        }
    }.lessThan);
    return rows;
}

fn buildBuildTimeRows() [bench_len]BenchmarkRow {
    @setEvalBranchQuota(10000);
    var rows: [bench_len]BenchmarkRow = undefined;
    const fields = @typeInfo(@TypeOf(bench_data)).@"struct".fields;
    inline for (fields, 0..) |field, i| {
        const d = @field(bench_data, field.name);
        rows[i] = .{
            .label = d.label,
            .value = -d.build_time_s, // negative so lower build time = longer bar
            .display = formatBuildTime(d.build_time_s),
            .url = getFrameworkUrl(d.id),
            .tooltip_metrics = &[_]TooltipMetric{
                .{ .label = "Framework", .value = d.label },
                .{ .label = "Build Time", .value = formatBuildTime(d.build_time_s) },
            },
        };
    }
    // Sort rows ascending by build time (lower is better, so -value is higher is better)
    std.sort.insertion(BenchmarkRow, &rows, {}, struct {
        fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool {
            return a.value > b.value;
        }
    }.lessThan);
    return rows;
}

fn buildColdStartRows() [bench_len]BenchmarkRow {
    @setEvalBranchQuota(10000);
    var rows: [bench_len]BenchmarkRow = undefined;
    const fields = @typeInfo(@TypeOf(bench_data)).@"struct".fields;
    inline for (fields, 0..) |field, i| {
        const d = @field(bench_data, field.name);
        rows[i] = .{
            .label = d.label,
            .value = -d.cold_start_ms, // negative so lower cold start = longer bar
            .display = formatColdStart(d.cold_start_ms),
            .url = getFrameworkUrl(d.id),
            .tooltip_metrics = &[_]TooltipMetric{
                .{ .label = "Framework", .value = d.label },
                .{ .label = "Cold Start", .value = formatColdStart(d.cold_start_ms) },
                .{ .label = "Image Size", .value = formatImageSize(d.image_mb) },
            },
        };
    }
    // Sort rows ascending by cold start (lower is better, so -value is higher is better)
    std.sort.insertion(BenchmarkRow, &rows, {}, struct {
        fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool {
            return a.value > b.value;
        }
    }.lessThan);
    return rows;
}

fn buildImageSizeRows() [bench_len]BenchmarkRow {
    @setEvalBranchQuota(10000);
    var rows: [bench_len]BenchmarkRow = undefined;
    const fields = @typeInfo(@TypeOf(bench_data)).@"struct".fields;
    inline for (fields, 0..) |field, i| {
        const d = @field(bench_data, field.name);
        rows[i] = .{
            .label = d.label,
            .value = -d.image_mb, // negative so smaller image = longer bar
            .display = formatImageSize(d.image_mb),
            .url = getFrameworkUrl(d.id),
            .tooltip_metrics = &[_]TooltipMetric{
                .{ .label = "Framework", .value = d.label },
                .{ .label = "Image Size", .value = formatImageSize(d.image_mb) },
                .{ .label = "Binary Size", .value = formatBinarySize(d.binary_mb) },
            },
        };
    }
    // Sort rows ascending by image size (lower is better, so -value is higher is better)
    std.sort.insertion(BenchmarkRow, &rows, {}, struct {
        fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool {
            return a.value > b.value;
        }
    }.lessThan);
    return rows;
}

fn buildCpuUsageRows() [bench_len]BenchmarkRow {
    @setEvalBranchQuota(10000);
    var rows: [bench_len]BenchmarkRow = undefined;
    const fields = @typeInfo(@TypeOf(bench_data)).@"struct".fields;
    inline for (fields, 0..) |field, i| {
        const d = @field(bench_data, field.name);
        rows[i] = .{
            .label = d.label,
            .value = -d.cpu_avg_pct, // negative so lower CPU = longer bar
            .display = formatCpuPeak(d.cpu_avg_pct),
            .url = getFrameworkUrl(d.id),
            .tooltip_metrics = &[_]TooltipMetric{
                .{ .label = "Framework", .value = d.label },
                .{ .label = "Avg CPU", .value = formatCpuPeak(d.cpu_avg_pct) },
                .{ .label = "Peak CPU", .value = formatCpuPeak(d.cpu_peak_pct) },
                .{ .label = "Requests/sec", .value = formatRequests(d.requests_per_sec) },
            },
        };
    }
    // Sort rows ascending by CPU usage (lower is better, so -value is higher is better)
    std.sort.insertion(BenchmarkRow, &rows, {}, struct {
        fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool {
            return a.value > b.value;
        }
    }.lessThan);
    return rows;
}

const benchmark_ssr_rows = buildSsrRows();
const benchmark_memory_rows = buildMemoryRows();
const benchmark_build_time_rows = buildBuildTimeRows();
const benchmark_cold_start_rows = buildColdStartRows();
const benchmark_image_size_rows = buildImageSizeRows();
const benchmark_cpu_usage_rows = buildCpuUsageRows();

const benchmark_tabs = [_]BenchmarkTab{
    // .{
    //     .id = "bench-tab-cwv",
    //     .label = "Core Web Vitals",
    //     .metric = "% of real-world sites with good Core Web Vitals",
    //     .footnote = "Full report. Benchmarked against Next.js and Leptos using real-world Core Web Vitals.",
    //     .rows = benchmark_cwv_rows[0..],
    //     .checked = true,
    // },
    .{
        .id = "bench-tab-ssr",
        .label = "SSR",
        .metric = "Requests per second (higher is better)",
        .footnote = "Dockerized SSR endpoint hit with 10k requests at 50 concurrent connections, averaged over 3 runs.",
        .rows = benchmark_ssr_rows[0..],
        .checked = true,
    },
    .{
        .id = "bench-tab-cpu",
        .label = "CPU",
        .metric = "Average CPU usage during load (lower is better)",
        .footnote = "Average CPU utilization during the load test via cgroup cpu.stat. Hover for peak CPU.",
        .rows = benchmark_cpu_usage_rows[0..],
        .checked = false,
    },
    .{
        .id = "bench-tab-memory",
        .label = "Memory",
        .metric = "Peak memory under load (lower is better)",
        .footnote = "Peak container RSS during load test. Lower is better. Hover for idle memory.",
        .rows = benchmark_memory_rows[0..],
        .checked = false,
    },
    .{
        .id = "bench-tab-cold-start",
        .label = "Cold Start",
        .metric = "Cold start time in milliseconds (lower is better)",
        .footnote = "Time for the container to start and become ready to serve requests. Lower is better.",
        .rows = benchmark_cold_start_rows[0..],
        .checked = false,
    },
    .{
        .id = "bench-tab-image-size",
        .label = "Size",
        .metric = "Docker image size (lower is better)",
        .footnote = "Size of the final Docker image. Smaller images are faster to deploy and use less storage.",
        .rows = benchmark_image_size_rows[0..],
        .checked = false,
    },
    .{
        .id = "bench-tab-build",
        .label = "Build Time",
        .metric = "Docker image build time in seconds (lower is better)",
        .footnote = "Time to build each framework's Docker image from scratch on the host machine. Lower is better.",
        .rows = benchmark_build_time_rows[0..],
        .checked = false,
    },

};

pub fn Page(ctx: zx.PageContext) zx.Component {
    const allocator = ctx.arena;
    const current_year = blk: {
        const timestamp = std.time.timestamp();
        const seconds_per_year = 365.25 * 24 * 60 * 60;
        const years_since_epoch = @as(i64, @intFromFloat(@as(f64, @floatFromInt(timestamp)) / seconds_per_year));
        break :blk 1970 + years_since_epoch;
    };

    // const overview_code = @embedFile("./examples/overview.zx");
    const feature_examples = normalizeFeatureExamples(
        allocator,
        @embedFile("./examples/feature_examples.zx"),
    );

    const control_tabs = [_]CodeTab{
        .{ .id = "control-tab-if", .label = "If", .section = "Control Flow: if", .code = "", .checked = true },
        .{ .id = "control-tab-if-opt", .label = "If Optional", .section = "Control Flow: if optional capture", .code = "", .checked = false },
        .{ .id = "control-tab-if-err", .label = "If Error", .section = "Control Flow: if error capture", .code = "", .checked = false },
        .{ .id = "control-tab-while", .label = "While", .section = "Control Flow: while", .code = "", .checked = false },
        .{ .id = "control-tab-while-opt", .label = "While Optional", .section = "Control Flow: while optional capture", .code = "", .checked = false },
        .{ .id = "control-tab-while-err", .label = "While Error", .section = "Control Flow: while error capture", .code = "", .checked = false },
    };

    const caching_tabs = [_]CodeTab{
        .{ .id = "caching-tab-component", .label = "Component", .section = "Caching: component", .code = "", .checked = true },
        .{ .id = "caching-tab-page", .label = "Page", .section = "Caching: page", .code = "", .checked = false },
    };

    const fs_tabs = [_]CodeTab{
        .{ .id = "fs-tab-page", .label = "Page", .section = "File System Routing: page", .code = "", .checked = true },
        .{ .id = "fs-tab-layout", .label = "Layout", .section = "File System Routing: layout", .code = "", .checked = false },
    };

    const component_tabs = [_]CodeTab{
        .{ .id = "component-tab-basics", .label = "Basics", .section = "Component: basics", .code = "", .checked = true },
        .{ .id = "component-tab-frag", .label = "Fragment", .section = "Component: fragment", .code = "", .checked = false },
        .{ .id = "component-tab-props", .label = "Props", .section = "Component: props", .code = "", .checked = false },
        .{ .id = "component-tab-attr", .label = "Attributes", .section = "Component: attr", .code = "", .checked = false },
    };

    return (
        <div @allocator={allocator}>
            <nav class="nav">
                <div class="nav-content">
                    <a href={root.configs.main_site_url} class="nav-logo">Ziex</a>
                    <input type="checkbox" id="nav-toggle" class="nav-toggle" />
                    <label for="nav-toggle" class="nav-hamburger" aria-label="Toggle menu">
                        <span></span>
                        <span></span>
                        <span></span>
                    </label>
                    <div class="nav-right">
                        <ul class="nav-links">
                            <li><a href="/learn" class="nav-link">Docs</a></li>
                            // <li><a href="/docs" class="nav-link"><span class="nav-link-full">Reference</span><span class="nav-link-short">Ref</span></a></li>
                            <li><a href="/playground" class="nav-link">Playground</a></li>
                        </ul>
                        <div class="nav-social" role="group" aria-label="Community links">
                            <a href="/r/discord" target="_blank" rel="noopener noreferrer" class="nav-social-link" aria-label="Discord">
                                <DiscordIcon allocator={allocator} />
                                <span class="nav-social-text">Discord</span>
                            </a>
                            <span class="nav-social-divider" aria-hidden="true"></span>
                            <a href={zx.info.repository} target="_blank" rel="noopener noreferrer" class="nav-social-link" aria-label="GitHub">
                                <GitHubIcon allocator={allocator} />
                                <span class="nav-social-text">GitHub</span>
                            </a>
                        </div>
                    </div>
                </div>
            </nav>
            <main>
                <section class="hero">
                    <div class="hero-visuals">
                        <div class="hero-visuals-grid"></div>
                        <div class="hero-visuals-dots"></div>
                        <div class="hero-visuals-scanline"></div>
                    </div>
                    <div class="hero-inner">
                        <div class="hero-content">
                            <div class="hero-badge">v{zx.info.version}</div>
                            <div class="hero-title-wrapper">
                                <h1 class="hero-title-main">Ziex</h1>
                                <div class="hero-title-accent">/</div>
                            </div>
                            <p class="hero-subtitle">
                                The full-stack web framework for Zig.
                            </p>
                            <p class="hero-description">
                                Compile-time safety, deterministic performance, and zero-dependency deployment. Build once, run everywhere.
                            </p>
                            <div class="hero-install">
                                <InstallCLI allocator={allocator} />
                            </div>
                            <div class="hero-cta">
                                <a href="/learn" class="btn btn-primary">Get Started</a>
                                <a href="/playground" class="btn btn-secondary">Playground</a>
                            </div>
                        </div>

                        <div class="hero-mascot">
                            <div class="hero-mascot-glow"></div>
                            // <div class="hero-mascot-glow hero-mascot-glow--inner"></div>
                            <img src="https://raw.githubusercontent.com/ziex-dev/branding/main/compressed/ziex-ziguana.webp" alt="Ziguana Mascot" />
                        </div>
                    </div>
                </section>
                <section class="features">
                    <div class="features-header">
                        <h2 class="section-title">Features</h2>
                        <p class="section-subtitle">
                            Everything you need to build fast, safe, and deployable web applications.
                        </p>
                    </div>
                    <div class="features-grid">
                        {for (features) |f| (<FeatureCard icon_fn={f.icon_fn} title={f.title} description={f.description} />)}
                    </div>
                </section>
                <BenchmarksSection eyebrow="" title="Performance" subtitle=`<a href='{zx.info.repository}/tree/main/bench' target='_blank' class='bench-label-link'>View benchmark →</a> <br/> Each framework runs in a Docker container limited to 2 CPU cores and 2 GB RAM.` tabs={benchmark_tabs[0..]} />
                // <ArchitectureSection allocator={allocator} />
                <DeploymentSection allocator={allocator} />
                // <TestingSection allocator={allocator} />
                // <TechnicalSection allocator={allocator} />
                <section class="feature-examples">
                    <div class="feature-examples-header">
                        <h2 class="section-title">Code Examples</h2>
                        <p class="section-subtitle">
                            Short, focused snippets that show how each feature feels in practice.
                        </p>
                    </div>
                    <div class="feature-examples-grid">
                        <FeatureExample title="Control Flow" wide={true} child={(<CodeWindowTabs id="control-flow-tabs" name="control-flow" title="" tabs={control_tabs[0..]} video_url="" source={feature_examples} />)} />
                        <FeatureExample title="Caching" wide={false} child={(<CodeWindowTabs id="caching-tabs" name="caching" title="" tabs={caching_tabs[0..]} video_url="" source={feature_examples} />)} />
                        <FeatureExample title="File System Routing" wide={false} child={(<CodeWindowTabs id="fs-routing-tabs" name="fs-routing" title="" tabs={fs_tabs[0..]} video_url="" source={feature_examples} />)} />
                        <FeatureExample title="Components" wide={false} child={(<CodeWindowTabs id="components-tabs" name="components" title="" tabs={component_tabs[0..]} video_url="" source={feature_examples} />)} />
                        <FeatureExample title="Dynamic Path" wide={false} child={(<CodeWindow title="pages/[id]/page.zx" section="Dynamic Path" source={feature_examples} code="" />)} />
                        <FeatureExample title="API Route" wide={false} child={(<CodeWindow title="route.zig" section="API Route" source={feature_examples} code="" />)} />
                        <FeatureExample title="WebSocket" wide={false} child={(<CodeWindow title="routes/ws/route.zig" section="WebSocket" source={feature_examples} code="" />)} />
                        <FeatureExample title="Client-side Rendering" wide={true} child={(<CodePreviewExample title="counter.zx" section="Client-side Rendering" source={feature_examples} code="" preview={(<Examples.Client />)} />)} />
                    </div>
                </section>
                // <section class="code-section">
                //     <div class="code-container">
                //         <div class="code-header">
                //             <h2 class="section-title">Familiar Syntax</h2>
                //             <p class="section-subtitle">
                //                 Familiar JSX like syntax or just like HTML with having access to Zig's control flow.
                //             </p>
                //         </div>
                //         <CodeWindow allocator={allocator} title="example.zx" section="" source="" code={overview_code} />
                //     </div>
                // </section>
            </main>
            <footer class="footer">
                <p>Copyright © {current_year} {" ziex.dev"}</p>
            </footer>
            <script src=`/assets/clipboard.js?v={zx.info.version}` defer="true"></script>
        </div>
    );
}

const Deployment = struct { icon_fn: *const fn (zx.Allocator) zx.Component, title: []const u8, description: []const u8 };
const Feature = struct { icon_fn: *const fn (zx.Allocator) zx.Component, title: []const u8, description: []const u8 };
fn FeatureCard(allocator: zx.Allocator, props: Feature) zx.Component {
    const IconComponent = props.icon_fn(allocator);
    return (
        <div @allocator={allocator} class="feature-card">
            <div class="feature-icon">{IconComponent}</div>
            <h3 class="feature-title">{props.title}</h3>
            <p class="feature-description">{props.description}</p>
        </div>
    );
}

const TooltipMetric = struct {
    label: []const u8,
    value: []const u8,
};

const BenchmarkRow = struct {
    label: []const u8,
    value: f64,
    display: []const u8,
    url: []const u8,
    tooltip_metrics: []const TooltipMetric = &[_]TooltipMetric{},
};

const BenchmarkRowViewProps = struct {
    row: BenchmarkRow,
    normalized_value: f64,
};

const BenchmarkTab = struct {
    id: []const u8,
    label: []const u8,
    metric: []const u8,
    footnote: []const u8,
    rows: []const BenchmarkRow,
    checked: bool,
};

const BenchmarksSectionProps = struct {
    eyebrow: []const u8,
    title: []const u8,
    subtitle: []const u8,
    tabs: []const BenchmarkTab,
};

fn buildBenchTabStyles(allocator: zx.Allocator, container_id: []const u8, tabs: []const BenchmarkTab) []const u8 {
    var out = std.array_list.Managed(u8).init(allocator);
    defer out.deinit();

    for (tabs) |tab| {
        out.appendSlice("#") catch unreachable;
        out.appendSlice(container_id) catch unreachable;
        out.appendSlice(":has(#") catch unreachable;
        out.appendSlice(tab.id) catch unreachable;
        out.appendSlice(":checked) .benchmarks-panel[data-tab=\"") catch unreachable;
        out.appendSlice(tab.id) catch unreachable;
        out.appendSlice("\"] { display: block; }\n") catch unreachable;

        out.appendSlice("#") catch unreachable;
        out.appendSlice(container_id) catch unreachable;
        out.appendSlice(":has(#") catch unreachable;
        out.appendSlice(tab.id) catch unreachable;
        out.appendSlice(":checked) label[for=\"") catch unreachable;
        out.appendSlice(tab.id) catch unreachable;
        out.appendSlice("\"] { color: #0c0f14; background: #4ade80; border-color: transparent; box-shadow: 0 8px 20px rgba(74, 222, 128, 0.25); }\n") catch unreachable;
    }

    return allocator.dupe(u8, out.items) catch unreachable;
}

fn BenchmarkRowView(allocator: zx.Allocator, props: BenchmarkRowViewProps) zx.Component {
    const style_value = std.fmt.allocPrint(allocator, "--value: {d:.3};", .{props.normalized_value}) catch unreachable;
    return (
        <div @allocator={allocator} class="bench-row" style={style_value}>
            <div class="bench-label">
                {if (props.row.url.len > 0) (
                    <a href={props.row.url} target="_blank" rel="noopener noreferrer" class="bench-label-link">{props.row.label}</a>
                ) else (
                    <span>{props.row.label}</span>
                )}
            </div>
            <div class="bench-bar"><span class="bench-bar-fill"></span></div>
            <div class="bench-value">{props.row.display}</div>
            <div class="bench-tooltip">
                {for (props.row.tooltip_metrics) |metric| (
                    <div class="bench-tooltip-row">
                        <span class="bench-tooltip-label">{metric.label}</span>
                        <span class="bench-tooltip-value">{metric.value}</span>
                    </div>
                )}
            </div>
        </div>
    );
}

fn roundToNiceValue(value: f64) f64 {
    if (value <= 0) return 1;

    const log_val = std.math.log10(value);
    const magnitude = std.math.pow(f64, 10, @floor(log_val));
    const normalized = value / magnitude;

    // Round up to nice values: 1, 2, 2.5, 3, 4, 5, 10
    // This ensures the highest bar fills to ~90% of space
    if (normalized <= 1) return magnitude;
    if (normalized <= 2) return magnitude * 2;
    if (normalized <= 2.5) return magnitude * 2.5;
    if (normalized <= 3) return magnitude * 3;
    if (normalized <= 4) return magnitude * 4;
    if (normalized <= 5) return magnitude * 5;
    return magnitude * 10;
}

fn normalizeValue(value: f64, rows: []const BenchmarkRow) f64 {
    const min_bar_value = 0.1; // 10% minimum bar size for visibility

    if (rows.len == 0) return 0;

    // Check if we're dealing with negative values (lower is better)
    const all_negative = blk: {
        for (rows) |row| {
            if (row.value >= 0) break :blk false;
        }
        break :blk true;
    };

    if (all_negative) {
        // For negative values: find min (most negative) and max (least negative)
        var min_value = rows[0].value;
        var max_value = rows[0].value;
        for (rows[1..]) |row| {
            if (row.value < min_value) min_value = row.value;
            if (row.value > max_value) max_value = row.value;
        }
        // Use absolute value for rounding calculation
        const rounded_range = roundToNiceValue(@abs(max_value - min_value));
        if (rounded_range == 0) return min_bar_value;
        const normalized = (value - min_value) / rounded_range;
        // Clamp to minimum bar size for visibility
        return if (normalized < min_bar_value) min_bar_value else normalized;
    } else {
        // For positive values: higher is better
        var max_value: f64 = 0;
        for (rows) |row| {
            if (row.value > max_value) {
                max_value = row.value;
            }
        }
        if (max_value <= 0) return min_bar_value;
        const rounded_max = roundToNiceValue(max_value);
        const normalized = value / rounded_max;
        // Clamp to minimum bar size for visibility
        return if (normalized < min_bar_value) min_bar_value else normalized;
    }
}

fn BenchmarksPanel(allocator: zx.Allocator, tab: BenchmarkTab) zx.Component {
    const panel_id = std.fmt.allocPrint(allocator, "panel-{s}", .{tab.id}) catch unreachable;
    const tab_id = std.fmt.allocPrint(allocator, "tab-{s}", .{tab.id}) catch unreachable;
    return (
        <div @allocator={allocator} class="benchmarks-panel" data-tab={tab.id} role="tabpanel" id={panel_id} aria-labelledby={tab_id}>
            <div class="benchmarks-metric">{tab.metric}</div>
            <div class="benchmarks-chart">
                {for (tab.rows) |row| (
                    <BenchmarkRowView row={row} normalized_value={normalizeValue(row.value, tab.rows)} />
                )}
            </div>
            <div class="benchmarks-footnote">{tab.footnote}</div>
        </div>
    );
}

fn BenchmarksSection(allocator: zx.Allocator, props: BenchmarksSectionProps) zx.Component {
    const tab_styles = buildBenchTabStyles(allocator, "benchmarks-tabs", props.tabs);
    return (
        <section @allocator={allocator} class="benchmarks">
            <div class="benchmarks-header">
                <span class="benchmarks-eyebrow">{props.eyebrow}</span>
                <h2 class="section-title">{props.title}</h2>
                <p class="section-subtitle" @escaping={.none}>{props.subtitle}</p>
            </div>
            <div id="benchmarks-tabs" class="benchmarks-card">
                <style @escaping={.none}>{tab_styles}</style>
                <div class="benchmarks-tabs" role="tablist" aria-label="Benchmark categories">
                    {for (props.tabs) |tab| (
                        <>
                            {if (tab.checked) (
                                <input type="radio" id={tab.id} name="bench-tabs" class="benchmarks-tab-radio" checked="true" aria-hidden="true" tabindex="-1" />
                            ) else (
                                <input type="radio" id={tab.id} name="bench-tabs" class="benchmarks-tab-radio" aria-hidden="true" tabindex="-1" />
                            )}
                            <label for={tab.id} class="benchmarks-tab-label" role="tab" id={std.fmt.allocPrint(allocator, "tab-{s}", .{tab.id}) catch unreachable} aria-selected={if (tab.checked) "true" else "false"} aria-controls={std.fmt.allocPrint(allocator, "panel-{s}", .{tab.id}) catch unreachable} tabindex={if (tab.checked) "0" else "-1"}>{tab.label}</label>
                        </>
                    )}
                </div>
                <div class="benchmarks-panels">
                    {for (props.tabs) |tab| (BenchmarksPanel(allocator, tab))}
                </div>
            </div>
        </section>
    );
}

const DeploymentSectionProps = struct {
    allocator: zx.Allocator,
};

fn DeploymentSection(allocator: zx.Allocator, _: DeploymentSectionProps) zx.Component {
    return (
        <section @allocator={allocator} class="deployment">
            <div class="deployment-header">
                <h2 class="section-title">Deploy Anywhere.</h2>
                <p class="section-subtitle">
                    Ziex compiles to a single, statically linked binary or a WASI module, making it compatible with every major cloud provider and edge network.
                </p>
            </div>
            <div class="deployment-grid">
                {for (deployments) |d| (
                    <div class="deployment-card">
                        <div class="deployment-card-icon">{d.icon_fn(allocator)}</div>
                        <h3 class="deployment-card-title">{d.title}</h3>
                        <p class="deployment-card-text">{d.description}</p>
                    </div>
                )}
            </div>
        </section>
    );
}

fn ArchitectureSection(allocator: zx.Allocator, _: struct {}) zx.Component {
    return (
        <section @allocator={allocator} class="architecture">
            <div class="architecture-header">
                <h2 class="section-title">Zero Overhead Pipeline</h2>
                <p class="section-subtitle">
                    A request in Ziex travels through a streamlined pipeline written in native Zig code, bypassing the heavy overhead of interpreted runtimes.
                </p>
            </div>
            <div class="architecture-diagram">
                <div class="architecture-node">
                    <div class="architecture-node-icon">{icons.Monitor(allocator)}</div>
                    <span class="architecture-node-label">Browser</span>
                </div>
                <div class="architecture-connector"></div>
                <div class="architecture-node">
                    <div class="architecture-node-icon">{icons.Server(allocator)}</div>
                    <span class="architecture-node-label">Ziex Edge</span>
                </div>
                <div class="architecture-connector"></div>
                <div class="architecture-node">
                    <div class="architecture-node-icon">{icons.Flow(allocator)}</div>
                    <span class="architecture-node-label">Zig Router</span>
                </div>
                <div class="architecture-connector"></div>
                <div class="architecture-node">
                    <div class="architecture-node-icon">{icons.Lightning(allocator)}</div>
                    <span class="architecture-node-label">Handler</span>
                </div>
                <div class="architecture-connector"></div>
                <div class="architecture-node">
                    <div class="architecture-node-icon">{icons.Layers(allocator)}</div>
                    <span class="architecture-node-label">Response</span>
                </div>
            </div>
        </section>
    );
}

fn TechnicalSection(allocator: zx.Allocator, _: struct {}) zx.Component {
    return (
        <section @allocator={allocator} class="technical">
            <div class="technical-grid">
                <div class="technical-card">
                    <span class="technical-card-eyebrow">Reliability</span>
                    <h3 class="technical-card-title">Statically Checked Components</h3>
                    <p class="technical-card-text">
                        Every tag, attribute, and component link is verified at compile-time. There are no runtime string-matching errors or missing props in production.
                    </p>
                </div>
                <div class="technical-card">
                    <span class="technical-card-eyebrow">Efficiency</span>
                    <h3 class="technical-card-title">Deterministic Allocation</h3>
                    <p class="technical-card-text">
                        Ziex uses arena allocators for every request. Memory is allocated once and cleared instantly when the request ends. Zero garbage collection, zero memory leaks.
                    </p>
                </div>
                <div class="technical-card">
                    <span class="technical-card-eyebrow">Resilience</span>
                    <h3 class="technical-card-title">WASI Isolation</h3>
                    <p class="technical-card-text">
                        Deploy your application inside a WASI sandbox. Hardware-level isolation ensures your app is secure and portable across any edge infrastructure.
                    </p>
                </div>
                <div class="technical-card">
                    <span class="technical-card-eyebrow">Speed</span>
                    <h3 class="technical-card-title">Native Binary Size</h3>
                    <p class="technical-card-text">
                        A typical Ziex application is less than 5MB. No node_modules, no shared libraries. Just a high-performance binary ready to serve.
                    </p>
                </div>
            </div>
        </section>
    );
}

fn TestingSection(allocator: zx.Allocator, _: struct {}) zx.Component {
    return (
        <section @allocator={allocator} class="testing">
            <div class="testing-header">
                <h2 class="section-title">Deterministic Simulation Testing</h2>
                <p class="section-subtitle">
                    Ziex components are tested using deterministic simulation. We simulate thousands of edge cases, network failures, and race conditions in milliseconds.
                </p>
            </div>
            <div class="testing-flex">
                <div class="clock-panel">
                    <div class="clock-wrapper">
                        <div class="clock-hand clock-hand--slow"></div>
                    </div>
                    <span class="clock-label">Local Time</span>
                    <span class="clock-time">Real World</span>
                </div>
                <div class="clock-panel">
                    <div class="clock-wrapper">
                        <div class="clock-hand clock-hand--fast"></div>
                    </div>
                    <span class="clock-label">Simulated Time</span>
                    <span class="clock-time">10,000x Speed</span>
                </div>
            </div>
        </section>
    );
}

const FeatureExampleProps = struct {
    title: []const u8,
    child: zx.Component,
    wide: bool,
};

fn FeatureExample(allocator: zx.Allocator, props: FeatureExampleProps) zx.Component {
    const class_name = if (props.wide) "feature-example feature-example--wide" else "feature-example";
    return (
        <div @allocator={allocator} class={class_name}>
            <div class="feature-example-title">{props.title}</div>
            {props.child}
        </div>
    );
}

const CodeWindowProps = struct {
    title: []const u8,
    code: []const u8,
    section: []const u8,
    source: []const u8,
};

fn normalizeFeatureExamples(allocator: zx.Allocator, content: []const u8) []const u8 {
    const step1 = replaceAll(allocator, content, "Caching__Page", "Page");
    return replaceAll(allocator, step1, "Routing__Page", "Page");
}

fn replaceAll(allocator: zx.Allocator, input: []const u8, needle: []const u8, replacement: []const u8) []const u8 {
    var out = std.array_list.Managed(u8).init(allocator);
    defer out.deinit();

    var start: usize = 0;
    while (std.mem.indexOfPos(u8, input, start, needle)) |idx| {
        out.appendSlice(input[start..idx]) catch unreachable;
        out.appendSlice(replacement) catch unreachable;
        start = idx + needle.len;
    }
    out.appendSlice(input[start..]) catch unreachable;

    return allocator.dupe(u8, out.items) catch unreachable;
}

const CodeTab = struct {
    id: []const u8,
    label: []const u8,
    section: []const u8,
    code: []const u8,
    checked: bool,
};

fn resolveCode(allocator: zx.Allocator, source: []const u8, section: []const u8, fallback: []const u8) []const u8 {
    const raw = if (section.len > 0 and source.len > 0)
        util.extractSection(allocator, source, section)
    else
        fallback;
    return util.highlightZx(allocator, raw) catch raw;
}

fn CodeWindow(allocator: zx.Allocator, props: CodeWindowProps) zx.Component {
    const highlighted = resolveCode(allocator, props.source, props.section, props.code);
    return (
        <div @allocator={allocator} class="code-example code-example--compact">
            <div class="code-example-header">
                <div class="code-example-dots">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="code-example-title">{props.title}</div>
            </div>
            <pre><code class="hljs" @escaping={.none}>{highlighted}</code></pre>
        </div>
    );
}

const CodeWindowTabsProps = struct {
    id: []const u8,
    name: []const u8,
    title: []const u8,
    tabs: []const CodeTab,
    video_url: []const u8,
    source: []const u8,
};

const CodePreviewExampleProps = struct {
    title: []const u8,
    section: []const u8,
    source: []const u8,
    code: []const u8,
    preview: zx.Component,
};

fn CodePreviewExample(allocator: zx.Allocator, props: CodePreviewExampleProps) zx.Component {
    const highlighted = resolveCode(allocator, props.source, props.section, props.code);
    return (
        <div @allocator={allocator} class="code-preview-example code-example code-example--compact">
            <div class="code-example-header">
                <div class="code-example-dots">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="code-example-title">{props.title}</div>
            </div>
            <div class="code-preview-body">
                <div class="code-preview-code">
                    <pre><code class="hljs" @escaping={.none}>{highlighted}</code></pre>
                </div>
                <div class="code-preview-pane">
                    <div class="code-preview-pane-header">Preview</div>
                    <div class="code-preview-pane-content">
                        {props.preview}
                    </div>
                </div>
            </div>
        </div>
    );
}

fn buildTabStyles(allocator: zx.Allocator, container_id: []const u8, tabs: []const CodeTab) []const u8 {
    var out = std.array_list.Managed(u8).init(allocator);
    defer out.deinit();

    for (tabs) |tab| {
        out.appendSlice("#") catch unreachable;
        out.appendSlice(container_id) catch unreachable;
        out.appendSlice(":has(#") catch unreachable;
        out.appendSlice(tab.id) catch unreachable;
        out.appendSlice(":checked) .code-example-panel[data-tab=\"") catch unreachable;
        out.appendSlice(tab.id) catch unreachable;
        out.appendSlice("\"] { display: block; }\n") catch unreachable;
    }

    return allocator.dupe(u8, out.items) catch unreachable;
}

fn CodeWindowTabs(allocator: zx.Allocator, props: CodeWindowTabsProps) zx.Component {
    const tab_styles = buildTabStyles(allocator, props.id, props.tabs);

    return (
        <div @allocator={allocator} id={props.id} class="code-example code-example--tabs code-example--compact">
            <style @escaping={.none}>{tab_styles}</style>
            <div class="code-example-header code-example-header--tabs">
                <div class="code-example-dots">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="code-example-tabs">
                    {for (props.tabs) |tab| (
                        <>
                            {if (tab.checked) (
                                <input type="radio" id={tab.id} name={props.name} class="code-example-tab-radio" checked="true" aria-label={tab.label} />
                            ) else (
                                <input type="radio" id={tab.id} name={props.name} class="code-example-tab-radio" aria-label={tab.label} />
                            )}
                            <label for={tab.id} class="code-example-tab-label">{tab.label}</label>
                        </>
                    )}
                </div>
                {if (props.video_url.len > 0) (
                    <a class="code-example-video" href={props.video_url} target="_blank" rel="noopener noreferrer" aria-label="Play video">
                        ▶
                    </a>
                )}
                {if (props.title.len > 0) (<div class="code-example-title">{props.title}</div>)}
            </div>
            <div class="code-example-panels">
                {for (props.tabs) |tab| (renderTabPanel(allocator, props.source, tab))}
            </div>
        </div>
    );
}

fn renderTabPanel(allocator: zx.Allocator, source: []const u8, tab: CodeTab) zx.Component {
    const highlighted = resolveCode(allocator, source, tab.section, tab.code);
    return (
        <div @allocator={allocator} class="code-example-panel" data-tab={tab.id}>
            <pre><code class="hljs" @escaping={.none}>{highlighted}</code></pre>
        </div>
    );
}

const std = @import("std");
const zx = @import("zx");
const util = @import("./reference/util.zig");
const icons = @import("./components/icons.zx");
const GitHubIcon = icons.GitHub;
const DiscordIcon = icons.Discord;
const InstallCLI = @import("./components/install_guide.zx").InstallCLI;
const Examples = @import("./examples/feature_examples.zx");
const root = @import("root");
