diff --git a/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/NavRailItem.razor b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/NavRailItem.razor
new file mode 100644
index 0000000..28e87f6
--- /dev/null
+++ b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/NavRailItem.razor
@@ -0,0 +1,12 @@
+@* Components/NavRailItem.razor *@
+
+ @if (Icon is not null) { @Icon }
+ @Text
+
+
+@code {
+ [Parameter, EditorRequired] public string Href { get; set; } = string.Empty;
+ [Parameter, EditorRequired] public string Text { get; set; } = string.Empty;
+ [Parameter] public RenderFragment? Icon { get; set; }
+ [Parameter] public NavLinkMatch Match { get; set; } = NavLinkMatch.Prefix;
+}
diff --git a/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/NavRailSection.razor b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/NavRailSection.razor
new file mode 100644
index 0000000..eb5bd5d
--- /dev/null
+++ b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/NavRailSection.razor
@@ -0,0 +1,12 @@
+@* Components/NavRailSection.razor — CSS-only collapsible (no JS, works in static SSR).
+ Apps that want cookie-persisted expand state keep their own interactive NavSection. *@
+
+ @Title
+ @ChildContent
+
+
+@code {
+ [Parameter, EditorRequired] public string Title { get; set; } = string.Empty;
+ [Parameter] public bool Expanded { get; set; } = true;
+ [Parameter] public RenderFragment? ChildContent { get; set; }
+}
diff --git a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/NavRailTests.cs b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/NavRailTests.cs
new file mode 100644
index 0000000..3e6ec95
--- /dev/null
+++ b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/NavRailTests.cs
@@ -0,0 +1,27 @@
+namespace ZB.MOM.WW.Theme.Tests;
+
+public class NavRailTests : TestContext
+{
+ [Fact]
+ public void NavRailItem_renders_rail_link_with_href_and_text()
+ {
+ var cut = RenderComponent(p => p
+ .Add(x => x.Href, "/clusters")
+ .Add(x => x.Text, "Clusters"));
+ var a = cut.Find("a.rail-link");
+ Assert.Equal("/clusters", a.GetAttribute("href"));
+ Assert.Contains("Clusters", a.TextContent);
+ }
+
+ [Fact]
+ public void NavRailSection_renders_title_and_children_open_by_default()
+ {
+ var cut = RenderComponent(p => p
+ .Add(x => x.Title, "Navigation")
+ .AddChildContent("X"));
+ var details = cut.Find("details.rail-section");
+ Assert.True(details.HasAttribute("open"));
+ Assert.Contains("Navigation", cut.Find("summary").TextContent);
+ Assert.NotNull(cut.Find(".rail-section-body .rail-link"));
+ }
+}