@page "/docs/contributing"
@namespace Lumeo.Docs.Pages.Docs

<PageTitle>Contributing — Lumeo</PageTitle>

<Container MaxWidth="3xl" Padding="0" Center="false">
<Stack Gap="10">

    <!-- Header -->
    <Stack Gap="4">
        <Heading Level="1" Size="3xl">Contributing</Heading>
        <Lumeo.Text Size="base" Color="muted" Leading="relaxed">
            Thank you for your interest in contributing to Lumeo. This guide walks through setting up the project,
            understanding the codebase structure, creating components, writing documentation, and running tests.
        </Lumeo.Text>
    </Stack>

    <Separator Class="my-4" />

    <!-- Getting Started -->
    <Stack Gap="6">
        <Heading Level="2">Getting started</Heading>

        <Stack Gap="3">
            <Heading Level="3">Prerequisites</Heading>
            <ul class="space-y-2 text-sm text-muted-foreground list-none">
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">.NET 10 SDK</strong> — Download from <Lumeo.Link Href="https://dotnet.microsoft.com/download" Class="text-foreground underline underline-offset-4 hover:text-muted-foreground transition-colors">dotnet.microsoft.com</Lumeo.Link>.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">Node.js</strong> — Required for Tailwind CSS processing. Any recent LTS version works.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">IDE</strong> — Visual Studio 2022+, JetBrains Rider, or VS Code with the C# Dev Kit extension.</span>
                </li>
            </ul>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">Clone and build</Heading>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">git clone https://github.com/aspect-build/lumeo.git
cd lumeo

# Build the component library
dotnet build src/Lumeo/Lumeo.csproj

# Run the docs site
dotnet run --project docs/Lumeo.Docs/Lumeo.Docs.csproj</Stack>
            <Lumeo.Text Size="sm" Color="muted">
                The docs site will be available at <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">https://localhost:5001</code> (or the port shown in your console).
            </Lumeo.Text>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">Build and pack</Heading>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre"># Build the library
dotnet build src/Lumeo/Lumeo.csproj

# Create a NuGet package
dotnet pack src/Lumeo/Lumeo.csproj</Stack>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Project Structure -->
    <Stack Gap="6">
        <Heading Level="2">Project structure</Heading>
        <Lumeo.Text Size="base" Color="muted" Leading="relaxed">
            The repository is organized into three main areas:
        </Lumeo.Text>

        <div class="overflow-x-auto rounded-lg border border-border/40">
            <Table>
                <TableHeader>
                    <TableRow>
                        <TableHead Class="w-56">Path</TableHead>
                        <TableHead>Description</TableHead>
                    </TableRow>
                </TableHeader>
                <TableBody>
                    <TableRow>
                        <TableCell Class="font-mono text-xs">src/Lumeo/</TableCell>
                        <TableCell>The component library. Published as the <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Lumeo</code> NuGet package.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-mono text-xs">src/Lumeo/UI/</TableCell>
                        <TableCell>All components, organized by name. Each component lives in its own folder (e.g. <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">UI/Button/</code>, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">UI/Dialog/</code>).</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-mono text-xs">src/Lumeo/Services/</TableCell>
                        <TableCell>Shared services: <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ToastService</code>, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">OverlayService</code>, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ThemeService</code>, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">KeyboardShortcutService</code>, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ComponentInteropService</code>.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-mono text-xs">src/Lumeo/wwwroot/</TableCell>
                        <TableCell>Static assets. CSS in <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">css/</code>, JavaScript in <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">js/</code>.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-mono text-xs">docs/Lumeo.Docs/</TableCell>
                        <TableCell>The documentation site (Blazor Server). Contains pages, layouts, and shared components.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-mono text-xs">tests/Lumeo.Tests/</TableCell>
                        <TableCell>Unit and integration tests using bUnit.</TableCell>
                    </TableRow>
                </TableBody>
            </Table>
        </div>
    </Stack>

    <Separator Class="my-4" />

    <!-- Creating a Component -->
    <Stack Gap="6">
        <Heading Level="2">Creating a component</Heading>
        <Lumeo.Text Size="base" Color="muted" Leading="relaxed">
            Every component follows a consistent structure. Here is a step-by-step guide.
        </Lumeo.Text>

        <Stack Gap="3">
            <Heading Level="3">1. Create the component folder</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Create a new folder under <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">src/Lumeo/UI/</code> named after your component.
                For example, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">src/Lumeo/UI/MyComponent/</code>.
            </Lumeo.Text>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">2. Follow the required conventions</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Every <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">.razor</code> file must include these elements:
            </Lumeo.Text>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">@@namespace Lumeo

&lt;div class="@@($"{BaseClasses} {Class}".Trim())"
     @@attributes="AdditionalAttributes"&gt;
    @@ChildContent
&lt;/div&gt;

@@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public string? Class { get; set; }
    [Parameter(CaptureUnmatchedValues = true)]
    public Dictionary&lt;string, object&gt;? AdditionalAttributes { get; set; }

    private string BaseClasses =&gt; "your-tailwind-classes-here";
}</Stack>

            <Lumeo.Text Size="sm" Color="muted" Class="mt-2">
                Key rules:
            </Lumeo.Text>
            <ul class="space-y-2 text-sm text-muted-foreground list-none">
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">@@namespace Lumeo</strong> must be the first line of every <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">.razor</code> file.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">Class parameter</strong> — Always include <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">[Parameter] public string? Class { get; set; }</code> for consumer CSS overrides.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">AdditionalAttributes</strong> — Always include <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">[Parameter(CaptureUnmatchedValues = true)]</code> and spread it on the root element with <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">@@attributes</code>.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">CSS class combining</strong> — Use the pattern <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">$"{BaseClasses} {Class}".Trim()</code> to merge base and consumer classes.</span>
                </li>
            </ul>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">3. Use CSS variables for all colors</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Never use hardcoded hex or HSL values. Always reference CSS variables through Tailwind utility classes:
            </Lumeo.Text>
            <div class="overflow-x-auto rounded-lg border border-border/40">
                <Table>
                    <TableHeader>
                        <TableRow>
                            <TableHead Class="w-56">Do</TableHead>
                            <TableHead Class="w-56">Do not</TableHead>
                        </TableRow>
                    </TableHeader>
                    <TableBody>
                        <TableRow>
                            <TableCell Class="font-mono text-xs text-green-500">bg-primary</TableCell>
                            <TableCell Class="font-mono text-xs text-destructive">bg-blue-500</TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell Class="font-mono text-xs text-green-500">text-foreground</TableCell>
                            <TableCell Class="font-mono text-xs text-destructive">text-gray-900</TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell Class="font-mono text-xs text-green-500">border-border</TableCell>
                            <TableCell Class="font-mono text-xs text-destructive">border-[#e5e7eb]</TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell Class="font-mono text-xs text-green-500">bg-muted</TableCell>
                            <TableCell Class="font-mono text-xs text-destructive">bg-[hsl(210,40%,96%)]</TableCell>
                        </TableRow>
                    </TableBody>
                </Table>
            </div>
            <Lumeo.Text Size="sm" Color="muted" Class="mt-2">
                Do <strong class="text-foreground">not</strong> use Tailwind <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">dark:</code> prefixes.
                Dark mode is handled entirely through CSS variable swaps in
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">lumeo.css</code>.
            </Lumeo.Text>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">4. Define enums inside the component</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                If your component needs variants, sizes, or other enumerated options, define the enum as a nested type inside the
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">@@code</code> block:
            </Lumeo.Text>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">@@code {
    [Parameter] public AlertVariant Variant { get; set; } = AlertVariant.Default;

    public enum AlertVariant
    {
        Default,
        Destructive,
        Success,
        Warning
    }
}</Stack>
            <Lumeo.Text Size="sm" Color="muted">
                Consumers reference these as <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Alert.AlertVariant.Success</code>.
            </Lumeo.Text>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">5. Use CascadingValue for state</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                When child components need to read parent state, use <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">CascadingValue</code> with a context record.
                Define the record as a nested type in the parent component. Use <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">IsFixed="false"</code> when the state can change.
            </Lumeo.Text>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">6. JS interop through ComponentInteropService</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Never inject <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">IJSRuntime</code> directly in components. Instead, inject
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ComponentInteropService</code> and call its methods:
            </Lumeo.Text>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">@@inject ComponentInteropService Interop

@@code {
    // Scroll locking for modals
    await Interop.LockScroll();
    await Interop.UnlockScroll();

    // Focus trapping for overlays
    await Interop.SetupFocusTrap(elementRef);
    await Interop.RemoveFocusTrap(elementRef);

    // Click-outside detection
    await Interop.RegisterClickOutside(elementRef, callback);
}</Stack>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">7. Icons</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Use the <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Blazicon</code> component
                from the <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Blazicons.Lucide</code> package:
            </Lumeo.Text>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">&lt;Blazicon Svg="Lucide.ChevronDown" class="h-4 w-4" /&gt;
&lt;Blazicon Svg="Lucide.X" class="h-4 w-4" /&gt;
&lt;Blazicon Svg="Lucide.Check" class="h-4 w-4" /&gt;</Stack>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Adding Documentation -->
    <Stack Gap="6">
        <Heading Level="2">Adding documentation</Heading>
        <Lumeo.Text Size="base" Color="muted" Leading="relaxed">
            Every component should have a corresponding documentation page in the docs site.
        </Lumeo.Text>

        <Stack Gap="3">
            <Heading Level="3">1. Create the page file</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Add a new <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">.razor</code> file
                under <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">docs/Lumeo.Docs/Pages/Components/</code>.
                Use this template:
            </Lumeo.Text>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">@@page "/components/my-component"
@@namespace Lumeo.Docs.Pages.Components

&lt;PageTitle&gt;MyComponent — Lumeo&lt;/PageTitle&gt;

&lt;Container MaxWidth="3xl" Padding="0" Center="false"&gt;
&lt;Stack Gap="10"&gt;
    &lt;!-- Header with title and description --&gt;
    &lt;!-- Live demos --&gt;
    &lt;!-- When to use section --&gt;
    &lt;!-- API reference table --&gt;
&lt;/Stack&gt;
&lt;/Container&gt;</Stack>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">2. Required sections</Heading>
            <ul class="space-y-2 text-sm text-muted-foreground list-none">
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">Header</strong> — Component name as an H1, followed by a brief description.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">Live demos</strong> — Interactive examples showing the component in action. Use bordered cards for each example.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">When to use</strong> — A list of appropriate use cases for the component.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span><strong class="text-foreground">API reference</strong> — A table listing all parameters with their types, defaults, and descriptions.</span>
                </li>
            </ul>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">3. Add to the navigation</Heading>
            <Lumeo.Text Size="sm" Color="muted">
                Open <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">docs/Lumeo.Docs/Layout/NavMenu.razor</code>
                and add a <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">&lt;NavLink&gt;</code> in the appropriate category section.
            </Lumeo.Text>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Running Tests -->
    <Stack Gap="6">
        <Heading Level="2">Running tests</Heading>
        <Lumeo.Text Size="base" Color="muted" Leading="relaxed">
            The test suite uses <Lumeo.Link Href="https://bunit.dev" Class="text-foreground underline underline-offset-4 hover:text-muted-foreground transition-colors">bUnit</Lumeo.Link>
            for component testing.
        </Lumeo.Text>

        <Stack Gap="3">
            <Heading Level="3">Run all tests</Heading>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">dotnet test</Stack>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">Run a specific test</Heading>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">dotnet test --filter "FullyQualifiedName~ButtonTests"</Stack>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">Test conventions</Heading>
            <ul class="space-y-2 text-sm text-muted-foreground list-none">
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span>Place tests in <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">tests/Lumeo.Tests/</code>, mirroring the source folder structure.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span>Name test files <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">{ComponentName}Tests.cs</code>.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span>Use bUnit's <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">RenderComponent&lt;T&gt;</code> to render and assert component output.</span>
                </li>
                <li class="flex items-start gap-2">
                    <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                    <span>Test default rendering, parameter variations, event callbacks, and accessibility attributes.</span>
                </li>
            </ul>
        </Stack>

        <Stack Gap="3">
            <Heading Level="3">Example test</Heading>
            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">using Bunit;
using Xunit;

public class ButtonTests : TestContext
{
    [Fact]
    public void Button_RendersDefaultVariant()
    {
        var cut = RenderComponent&lt;Button&gt;(parameters =&gt;
            parameters.AddChildContent("Click me"));

        cut.Find("button").MarkupMatches(
            "&lt;button class='...'&gt;Click me&lt;/button&gt;");
    }

    [Fact]
    public void Button_FiresOnClick()
    {
        var clicked = false;
        var cut = RenderComponent&lt;Button&gt;(parameters =&gt; parameters
            .AddChildContent("Click")
            .Add(p =&gt; p.OnClick,
                 EventCallback.Factory.Create(this, () =&gt; clicked = true)));

        cut.Find("button").Click();
        Assert.True(clicked);
    }
}</Stack>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Code Style -->
    <Stack Gap="6">
        <Heading Level="2">Code style</Heading>
        <Lumeo.Text Size="base" Color="muted" Leading="relaxed">
            Consistent code style keeps the codebase readable and maintainable. Here are the key conventions.
        </Lumeo.Text>

        <div class="overflow-x-auto rounded-lg border border-border/40">
            <Table>
                <TableHeader>
                    <TableRow>
                        <TableHead Class="w-48">Area</TableHead>
                        <TableHead>Convention</TableHead>
                    </TableRow>
                </TableHeader>
                <TableBody>
                    <TableRow>
                        <TableCell Class="font-medium">CSS framework</TableCell>
                        <TableCell>Tailwind CSS v4. All utility classes applied inline.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Colors</TableCell>
                        <TableCell>CSS variables only (<code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">bg-primary</code>, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">text-foreground</code>, etc.). No hardcoded hex/HSL values.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Dark mode</TableCell>
                        <TableCell>Handled by CSS variable swaps in <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">lumeo.css</code>. Never use <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">dark:</code> Tailwind prefixes.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Namespace</TableCell>
                        <TableCell>All component files use <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">@@namespace Lumeo</code>.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Two-way binding</TableCell>
                        <TableCell><code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Property</code> + <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">PropertyChanged</code> EventCallback pairs.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">JS interop</TableCell>
                        <TableCell>Always through <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ComponentInteropService</code>. Never inject <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">IJSRuntime</code> directly.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Enums</TableCell>
                        <TableCell>Defined as nested types inside the component's <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">@@code</code> block.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Context records</TableCell>
                        <TableCell>Defined as nested <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">public record</code> inside the parent component.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Overlay cleanup</TableCell>
                        <TableCell>Implement <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">IAsyncDisposable</code>. Handle <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">JSDisconnectedException</code> in cleanup.</TableCell>
                    </TableRow>
                    <TableRow>
                        <TableCell Class="font-medium">Icons</TableCell>
                        <TableCell>Use <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">&lt;Blazicon Svg="Lucide.X" /&gt;</code> from <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Blazicons.Lucide</code>.</TableCell>
                    </TableRow>
                </TableBody>
            </Table>
        </div>
    </Stack>

    <Separator Class="my-4" />

    <!-- Pull Request Guidelines -->
    <Stack Gap="4">
        <Heading Level="2">Pull request guidelines</Heading>
        <ul class="space-y-2 text-sm text-muted-foreground list-none">
            <li class="flex items-start gap-2">
                <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                <span><strong class="text-foreground">One component per PR.</strong> Keep pull requests focused. If your change affects multiple components, split them into separate PRs.</span>
            </li>
            <li class="flex items-start gap-2">
                <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                <span><strong class="text-foreground">Include documentation.</strong> New components should come with a documentation page. Changes to existing components should update the relevant docs.</span>
            </li>
            <li class="flex items-start gap-2">
                <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                <span><strong class="text-foreground">Add tests.</strong> Include bUnit tests that cover the default rendering, parameter variations, and key interactions.</span>
            </li>
            <li class="flex items-start gap-2">
                <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                <span><strong class="text-foreground">Build must pass.</strong> Run <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">dotnet build src/Lumeo/Lumeo.csproj</code> and <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">dotnet test</code> before submitting.</span>
            </li>
            <li class="flex items-start gap-2">
                <Lumeo.Text As="span" Class="mt-1.5 h-1.5 w-1.5 rounded-full bg-foreground shrink-0"></Lumeo.Text>
                <span><strong class="text-foreground">Descriptive commit messages.</strong> Use clear, concise commit messages that describe the "why" behind the change.</span>
            </li>
        </ul>
    </Stack>

</Stack>
</Container>
