This is an automated email from the ASF dual-hosted git repository.

janhoy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-orbit.git


The following commit(s) were added to refs/heads/main by this push:
     new d9a005e6 Replace just-the-docs with custom Solr-branded Jekyll theme 
(#25)
d9a005e6 is described below

commit d9a005e6218204c6d551cb5673c4ad1c0a335cb5
Author: Jan Høydahl <[email protected]>
AuthorDate: Mon May 25 01:52:05 2026 +0200

    Replace just-the-docs with custom Solr-branded Jekyll theme (#25)
    
    Enables GitHub Pages via .asf.yaml ghp_branch/ghp_path, eliminating
    the need for a GitHub Actions docs workflow.
---
 .asf.yaml                        |   4 +
 .github/workflows/docs.yml       |  61 ---------------
 docs/Gemfile                     |   3 +-
 docs/_config.yml                 |  65 +++-------------
 docs/_includes/breadcrumbs.html  |  28 +++++++
 docs/_includes/footer.html       |  11 +++
 docs/_includes/head.html         |  12 +++
 docs/_includes/header.html       |  24 ++++++
 docs/_includes/nav.html          |  55 +++++++++++++
 docs/_layouts/default.html       |  41 ++++++++++
 docs/_sass/_base.scss            | 110 ++++++++++++++++++++++++++
 docs/_sass/_callouts.scss        |  28 +++++++
 docs/_sass/_content.scss         |  40 ++++++++++
 docs/_sass/_layout.scss          | 162 +++++++++++++++++++++++++++++++++++++++
 docs/_sass/_nav.scss             | 130 +++++++++++++++++++++++++++++++
 docs/_sass/_responsive.scss      |  33 ++++++++
 docs/_sass/_search.scss          |  61 +++++++++++++++
 docs/_sass/_variables.scss       |  50 ++++++++++++
 docs/assets/css/main.scss        |  10 +++
 docs/assets/images/solr-logo.svg |  40 ++++++++++
 docs/assets/js/app.js            | 136 ++++++++++++++++++++++++++++++++
 docs/search.json                 |   6 ++
 22 files changed, 994 insertions(+), 116 deletions(-)

diff --git a/.asf.yaml b/.asf.yaml
index e308249d..25f49465 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -30,6 +30,10 @@ github:
     # Auto-delete head branch after a PR is merged
     del_branch_on_merge: true
 
+  # Enable GitHub Pages from docs/ on main branch
+  ghp_branch: main
+  ghp_path: /docs
+
   # Disabled autolinking of JIRA tickets since it messes up links to GH issues
   #autolink_jira:
   #  - SOLR
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
deleted file mode 100644
index 7b8cd176..00000000
--- a/.github/workflows/docs.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-name: Deploy docs to GitHub Pages
-
-on:
-  push:
-    branches: ["main"]
-    paths:
-      - "docs/**"
-      - ".github/workflows/docs.yml"
-  workflow_dispatch:
-
-permissions:
-  contents: read
-  pages: write
-  id-token: write
-
-concurrency:
-  group: "pages"
-  cancel-in-progress: true
-
-jobs:
-  build:
-    runs-on: ubuntu-latest
-    defaults:
-      run:
-        working-directory: docs
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-
-      - name: Setup Ruby
-        uses: ruby/setup-ruby@v1
-        with:
-          ruby-version: "3.3"
-          bundler-cache: true
-          cache-version: 0
-          working-directory: docs
-
-      - name: Setup Pages
-        id: pages
-        uses: actions/configure-pages@v5
-
-      - name: Build with Jekyll
-        run: bundle exec jekyll build --baseurl "${{ 
steps.pages.outputs.base_path }}"
-        env:
-          JEKYLL_ENV: production
-
-      - name: Upload artifact
-        uses: actions/upload-pages-artifact@v4
-        with:
-          path: docs/_site
-
-  deploy:
-    environment:
-      name: github-pages
-      url: ${{ steps.deployment.outputs.page_url }}
-    runs-on: ubuntu-latest
-    needs: build
-    steps:
-      - name: Deploy to GitHub Pages
-        id: deployment
-        uses: actions/deploy-pages@v4
diff --git a/docs/Gemfile b/docs/Gemfile
index b3fbcd5e..c99d6dd1 100644
--- a/docs/Gemfile
+++ b/docs/Gemfile
@@ -1,4 +1,3 @@
 source "https://rubygems.org";
 
-gem "jekyll", "~> 4.4.1"
-gem "just-the-docs", "0.12.0"
+gem "jekyll"
diff --git a/docs/_config.yml b/docs/_config.yml
index 098be17a..95b5ccf0 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -3,71 +3,30 @@ description: >-
   A performance benchmarking tool for Apache Solr clusters,
   derived from OpenSearch Benchmark.
 
-theme: just-the-docs
-
 url: https://apache.github.io
-# baseurl is injected automatically by actions/configure-pages during CI
-
-aux_links:
-  "GitHub": https://github.com/apache/solr-orbit
-  "Apache Solr": https://solr.apache.org
-  "Apache Software Foundation": https://www.apache.org
-
-aux_links_new_tab: true
-
-search_enabled: true
-
-search:
-  heading_level: 2
-  previews: 3
-  preview_words_before: 5
-  preview_words_after: 10
-
-# Callout blocks
-callouts:
-  note:
-    title: Note
-    color: blue
-  warning:
-    title: Warning
-    color: yellow
-  important:
-    title: Important
-    color: red
+baseurl: /solr-orbit
 
-# Back to top link
-back_to_top: true
-back_to_top_text: "Back to top"
+# Site links used in templates
+github_url: https://github.com/apache/solr-orbit
+solr_url:   https://solr.apache.org
 
-# Footer
-last_edit_timestamp: true
-last_edit_time_format: "%b %e %Y at %I:%M %p"
-
-# Heading anchors
-heading_anchors: true
-
-# External navigation links
-nav_external_links:
-  - title: Apache Solr
-    url: https://solr.apache.org
-  - title: ASF
-    url: https://www.apache.org
-
-# Color scheme (light by default)
-color_scheme: light
-
-# Apply the just-the-docs layout to every page by default
+# Apply the default layout to all pages
 defaults:
   - scope:
       path: ""
     values:
       layout: "default"
 
-# Suppress @import deprecation warnings from the just-the-docs gem's SCSS
+# Markdown
 sass:
   quiet_deps: true
 
-# Exclude from processing
+markdown: kramdown
+kramdown:
+  input: GFM
+  syntax_highlighter: rouge
+
+# Exclude from build
 exclude:
   - Gemfile
   - Gemfile.lock
diff --git a/docs/_includes/breadcrumbs.html b/docs/_includes/breadcrumbs.html
new file mode 100644
index 00000000..bb0b658c
--- /dev/null
+++ b/docs/_includes/breadcrumbs.html
@@ -0,0 +1,28 @@
+{% if page.parent or page.grand_parent %}
+<nav class="breadcrumbs" aria-label="Breadcrumb">
+  <a href="{{ '/' | relative_url }}">Home</a>
+  <span class="sep">›</span>
+
+  {% if page.grand_parent %}
+    {% assign gp_page = site.pages | where: "title", page.grand_parent | first 
%}
+    {% if gp_page %}
+      <a href="{{ gp_page.url | relative_url }}">{{ page.grand_parent }}</a>
+    {% else %}
+      <span>{{ page.grand_parent }}</span>
+    {% endif %}
+    <span class="sep">›</span>
+  {% endif %}
+
+  {% if page.parent %}
+    {% assign parent_page = site.pages | where: "title", page.parent | first %}
+    {% if parent_page %}
+      <a href="{{ parent_page.url | relative_url }}">{{ page.parent }}</a>
+    {% else %}
+      <span>{{ page.parent }}</span>
+    {% endif %}
+    <span class="sep">›</span>
+  {% endif %}
+
+  <span class="current">{{ page.title }}</span>
+</nav>
+{% endif %}
diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html
new file mode 100644
index 00000000..0998f745
--- /dev/null
+++ b/docs/_includes/footer.html
@@ -0,0 +1,11 @@
+<footer class="site-footer">
+  <p>
+    Copyright &copy; 2024–{% assign y = site.time | date: "%Y" %}{{ y }}
+    <a href="https://www.apache.org/";>The Apache Software Foundation</a>.
+    Licensed under the <a 
href="https://www.apache.org/licenses/LICENSE-2.0";>Apache License, Version 
2.0</a>.
+  </p>
+  <p>
+    Apache, Apache Solr, and the Apache feather logo are trademarks of The 
Apache Software Foundation.
+    See <a href="{{ '/about' | relative_url }}">About / Credits</a> for full 
attribution and trademark notices.
+  </p>
+</footer>
diff --git a/docs/_includes/head.html b/docs/_includes/head.html
new file mode 100644
index 00000000..24b6b823
--- /dev/null
+++ b/docs/_includes/head.html
@@ -0,0 +1,12 @@
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>{% if page.title and page.title != site.title %}{{ page.title }} — {{ 
site.title }}{% else %}{{ site.title }}{% endif %}</title>
+  {% if page.description %}<meta name="description" content="{{ 
page.description | escape }}">
+  {% elsif site.description %}<meta name="description" content="{{ 
site.description | escape }}">{% endif %}
+  <link rel="preconnect" href="https://fonts.googleapis.com";>
+  <link rel="preconnect" href="https://fonts.gstatic.com"; crossorigin>
+  <link 
href="https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700&display=swap";
 rel="stylesheet">
+  <link rel="stylesheet" href="{{ '/assets/css/main.css' | relative_url }}">
+  <link rel="icon" href="https://solr.apache.org/theme/images/favicon.png"; 
type="image/png">
+</head>
diff --git a/docs/_includes/header.html b/docs/_includes/header.html
new file mode 100644
index 00000000..8cf12a7e
--- /dev/null
+++ b/docs/_includes/header.html
@@ -0,0 +1,24 @@
+<header class="site-header">
+  <div class="header-inner">
+    <a href="{{ '/' | relative_url }}" class="site-logo">
+      <img src="{{ '/assets/images/solr-logo.svg' | relative_url }}" 
alt="Apache Solr" height="32">
+      <span class="site-name">Orbit Docs</span>
+    </a>
+
+    <div class="search-wrap">
+      <input type="search" id="search-input" class="search-input"
+             placeholder="Search docs…" autocomplete="off" aria-label="Search 
documentation">
+      <div class="search-results" id="search-results" role="listbox"></div>
+    </div>
+
+    <div class="header-spacer"></div>
+
+    <nav class="header-links" aria-label="External links">
+      <a href="{{ site.solr_url }}" class="header-link" target="_blank" 
rel="noopener">Apache Solr</a>
+      <a href="{{ site.github_url }}" class="header-link" target="_blank" 
rel="noopener">GitHub</a>
+    </nav>
+
+    <button class="mobile-menu-btn" id="mobile-menu-btn"
+            aria-label="Toggle navigation" aria-expanded="false" 
aria-controls="sidebar">&#9776;</button>
+  </div>
+</header>
diff --git a/docs/_includes/nav.html b/docs/_includes/nav.html
new file mode 100644
index 00000000..a0d15d89
--- /dev/null
+++ b/docs/_includes/nav.html
@@ -0,0 +1,55 @@
+{% assign nav_pages = site.pages | where_exp: "p", "p.nav_order != nil" %}
+{% assign root_pages = nav_pages | where_exp: "p", "p.parent == nil" | sort: 
"nav_order" %}
+
+<ul class="nav-list" role="tree">
+{% for root in root_pages %}{% if root.title %}
+  {%- assign root_children = nav_pages | where: "parent", root.title | 
where_exp: "c", "c.grand_parent == nil" | sort: "nav_order" -%}
+
+  {%- comment %}Determine active state{% endcomment -%}
+  {%- assign root_active = false -%}
+  {%- if page.url == root.url -%}{%- assign root_active = true -%}{%- endif -%}
+  {%- if page.parent == root.title and page.grand_parent == nil -%}{%- assign 
root_active = true -%}{%- endif -%}
+  {%- if page.grand_parent == root.title -%}{%- assign root_active = true 
-%}{%- endif -%}
+
+  <li class="nav-item{% if root_active %} active{% endif %}" role="treeitem">
+    {% if root_children.size > 0 %}
+      <div class="nav-row">
+        <a href="{{ root.url | relative_url }}" class="nav-root-link">{{ 
root.title }}</a>
+        <button class="nav-toggle-btn{% if root_active %} open{% endif %}" 
aria-label="Toggle {{ root.title }}">
+          <span class="caret">&#9654;</span>
+        </button>
+      </div>
+      <ul class="nav-children{% if root_active %} open{% endif %}" 
role="group">
+        {% for child in root_children %}{% if child.title %}
+          {%- assign child_gc = nav_pages | where: "parent", child.title | 
where: "grand_parent", root.title | sort: "nav_order" -%}
+          {%- assign child_active = false -%}
+          {%- if page.url == child.url -%}{%- assign child_active = true 
-%}{%- endif -%}
+          {%- if page.parent == child.title and page.grand_parent == 
root.title -%}{%- assign child_active = true -%}{%- endif -%}
+
+          <li class="nav-item{% if child_active %} active{% endif %}" 
role="treeitem">
+            {% if child_gc.size > 0 %}
+              <div class="nav-row">
+                <a href="{{ child.url | relative_url }}" 
class="nav-child-link">{{ child.title }}</a>
+                <button class="nav-toggle-btn{% if child_active %} open{% 
endif %}" aria-label="Toggle {{ child.title }}">
+                  <span class="caret">&#9654;</span>
+                </button>
+              </div>
+              <ul class="nav-grandchildren{% if child_active %} open{% endif 
%}" role="group">
+                {% for gc in child_gc %}{% if gc.title %}
+                  <li class="nav-item{% if page.url == gc.url %} active{% 
endif %}" role="treeitem">
+                    <a href="{{ gc.url | relative_url }}" 
class="nav-gc-link">{{ gc.title }}</a>
+                  </li>
+                {% endif %}{% endfor %}
+              </ul>
+            {% else %}
+              <a href="{{ child.url | relative_url }}" 
class="nav-child-link">{{ child.title }}</a>
+            {% endif %}
+          </li>
+        {% endif %}{% endfor %}
+      </ul>
+    {% else %}
+      <a href="{{ root.url | relative_url }}" class="nav-root-link">{{ 
root.title }}</a>
+    {% endif %}
+  </li>
+{% endif %}{% endfor %}
+</ul>
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
new file mode 100644
index 00000000..6d6b36b3
--- /dev/null
+++ b/docs/_layouts/default.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+{% include head.html %}
+<body>
+<div class="site-wrapper">
+
+  {% include header.html %}
+
+  <div class="sidebar-overlay" id="sidebar-overlay"></div>
+
+  <div class="page-body">
+    <nav class="sidebar" id="sidebar" aria-label="Site navigation">
+      <div class="sidebar-inner">
+        {% include nav.html %}
+      </div>
+    </nav>
+
+    <main class="content" id="main-content">
+      <div class="content-inner">
+        {% include breadcrumbs.html %}
+        <article class="page-content">
+          {{ content }}
+        </article>
+        <div class="page-meta">
+          <a href="{{ site.github_url }}/edit/main/docs/{{ page.path }}" 
target="_blank" rel="noopener">
+            Edit this page on GitHub
+          </a>
+        </div>
+      </div>
+    </main>
+  </div>
+
+  {% include footer.html %}
+
+</div>
+
+<button class="back-to-top" id="back-to-top" aria-label="Back to top" 
title="Back to top">&#8679;</button>
+
+<script src="{{ '/assets/js/app.js' | relative_url }}"></script>
+</body>
+</html>
diff --git a/docs/_sass/_base.scss b/docs/_sass/_base.scss
new file mode 100644
index 00000000..adb597d3
--- /dev/null
+++ b/docs/_sass/_base.scss
@@ -0,0 +1,110 @@
+*, *::before, *::after { box-sizing: border-box; }
+
+html {
+  font-size: $base-font-size;
+  scroll-behavior: smooth;
+  -webkit-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+  font-family: $font-family;
+  font-weight: 400;
+  line-height: $base-line-height;
+  color: $body-text;
+  background: $background;
+}
+
+a {
+  color: $solr-orange;
+  text-decoration: none;
+  &:hover { color: $solr-orange-dark; text-decoration: underline; }
+}
+
+h1, h2, h3, h4, h5, h6 {
+  font-family: $font-family;
+  font-weight: 600;
+  line-height: 1.3;
+  margin: $sp5 0 $sp3;
+  color: $solr-dark;
+}
+h1 { font-size: 1.875rem; font-weight: 700; color: $solr-orange; margin-top: 
0; }
+h2 { font-size: 1.375rem; border-bottom: 1px solid $border-color; 
padding-bottom: $sp2; }
+h3 { font-size: 1.125rem; }
+h4 { font-size: 1rem; }
+h5 { font-size: 0.9375rem; }
+h6 { font-size: 0.875rem; color: $muted-text; }
+
+p { margin: 0 0 $sp3; }
+
+ul, ol { margin: 0 0 $sp3; padding-left: $sp5; }
+li { margin-bottom: $sp1; }
+li > ul, li > ol { margin-top: $sp1; margin-bottom: 0; }
+
+code {
+  font-family: $font-mono;
+  font-size: 0.875em;
+  background: $code-bg;
+  color: $code-text;
+  padding: 2px 5px;
+  border-radius: 3px;
+  border: 1px solid #e0e0e0;
+}
+
+pre {
+  background: $solr-dark;
+  color: #f8f8f2;
+  padding: $sp4;
+  border-radius: 6px;
+  overflow-x: auto;
+  margin: 0 0 $sp4;
+  line-height: 1.5;
+  code {
+    background: none;
+    border: none;
+    padding: 0;
+    color: inherit;
+    font-size: 0.875rem;
+  }
+}
+
+table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: $sp4;
+  font-size: 0.9375rem;
+  th {
+    background: $solr-dark;
+    color: #fff;
+    font-weight: 600;
+    text-align: left;
+    padding: $sp2 $sp3;
+    border: 1px solid #3c3851;
+  }
+  td {
+    padding: $sp2 $sp3;
+    border: 1px solid $border-color;
+    vertical-align: top;
+  }
+  tr:nth-child(even) td { background: $bg-alt; }
+}
+
+blockquote {
+  margin: 0 0 $sp4;
+  padding: $sp3 $sp4;
+  border-left: 4px solid $border-color;
+  color: $muted-text;
+  background: $bg-alt;
+  border-radius: 0 4px 4px 0;
+  p:last-child { margin-bottom: 0; }
+}
+
+hr { border: none; border-top: 1px solid $border-color; margin: $sp5 0; }
+
+img { max-width: 100%; height: auto; }
+
+strong { font-weight: 700; }
+em { font-style: italic; }
+
+// Rouge syntax highlighting
+.highlight { margin: 0 0 $sp4; border-radius: 6px; overflow: hidden; }
diff --git a/docs/_sass/_callouts.scss b/docs/_sass/_callouts.scss
new file mode 100644
index 00000000..e53b4d29
--- /dev/null
+++ b/docs/_sass/_callouts.scss
@@ -0,0 +1,28 @@
+// Callout blocks — support Kramdown IAL: {: .note }, {: .warning }, {: 
.important }
+// Applied to both <p class="note"> and <blockquote class="note">
+
+@mixin callout($border, $bg, $label-color, $label-text) {
+  padding: $sp3 $sp4 $sp3 calc(#{$sp4} + 4px);
+  border-left: 4px solid $border;
+  background: $bg;
+  border-radius: 0 6px 6px 0;
+  margin: $sp4 0;
+  color: $body-text;
+
+  &::before {
+    content: $label-text;
+    display: block;
+    font-weight: 700;
+    font-size: 0.75rem;
+    letter-spacing: 0.06em;
+    text-transform: uppercase;
+    color: $label-color;
+    margin-bottom: 4px;
+  }
+
+  p:last-child, &:last-child { margin-bottom: 0; }
+}
+
+p.note, blockquote.note       { @include callout($note-border,      $note-bg,  
    $note-label,      'Note'); }
+p.warning, blockquote.warning  { @include callout($warning-border,   
$warning-bg,   $warning-label,   'Warning'); }
+p.important, blockquote.important { @include callout($important-border, 
$important-bg, $important-label, 'Important'); }
diff --git a/docs/_sass/_content.scss b/docs/_sass/_content.scss
new file mode 100644
index 00000000..ed0dec7f
--- /dev/null
+++ b/docs/_sass/_content.scss
@@ -0,0 +1,40 @@
+// ── Breadcrumbs ────────────────────────────────────────
+.breadcrumbs {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 6px;
+  font-size: 0.8125rem;
+  color: $muted-text;
+  margin-bottom: $sp4;
+
+  a { color: $muted-text; &:hover { color: $solr-orange; text-decoration: 
none; } }
+  .sep { opacity: 0.45; font-size: 0.7rem; }
+  .current { color: $body-text; font-weight: 500; }
+}
+
+// ── Page meta (edit link) ──────────────────────────────
+.page-meta {
+  margin-top: $sp6;
+  padding-top: $sp4;
+  border-top: 1px solid $border-color;
+  font-size: 0.8125rem;
+  color: $muted-text;
+  a { color: $muted-text; &:hover { color: $solr-orange; } }
+}
+
+// ── Heading anchor links ───────────────────────────────
+.heading-anchor {
+  opacity: 0;
+  margin-left: $sp2;
+  color: $muted-text;
+  font-size: 0.8em;
+  font-weight: 400;
+  transition: opacity 0.15s;
+  text-decoration: none;
+  &:hover { color: $solr-orange; text-decoration: none; }
+}
+
+h2:hover .heading-anchor,
+h3:hover .heading-anchor,
+h4:hover .heading-anchor { opacity: 1; }
diff --git a/docs/_sass/_layout.scss b/docs/_sass/_layout.scss
new file mode 100644
index 00000000..aa94f2d5
--- /dev/null
+++ b/docs/_sass/_layout.scss
@@ -0,0 +1,162 @@
+.site-wrapper {
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+}
+
+// ── Header ─────────────────────────────────────────────
+.site-header {
+  position: fixed;
+  top: 0; left: 0; right: 0;
+  height: $header-height;
+  background: $solr-dark;
+  z-index: 1000;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
+
+  .header-inner {
+    display: flex;
+    align-items: center;
+    height: 100%;
+    padding: 0 $sp4;
+    gap: $sp3;
+  }
+}
+
+.site-logo {
+  display: flex;
+  align-items: center;
+  gap: $sp3;
+  text-decoration: none;
+  flex-shrink: 0;
+
+  img { height: 32px; width: auto; }
+
+  .site-name {
+    color: rgba(255,255,255,0.55);
+    font-size: 0.8125rem;
+    font-weight: 400;
+    letter-spacing: 0.03em;
+    border-left: 1px solid rgba(255,255,255,0.2);
+    padding-left: $sp3;
+    white-space: nowrap;
+  }
+
+  &:hover { text-decoration: none; .site-name { color: rgba(255,255,255,0.85); 
} }
+}
+
+.header-spacer { flex: 1; }
+
+.header-links {
+  display: flex;
+  align-items: center;
+  gap: $sp2;
+}
+
+.header-link {
+  color: rgba(255,255,255,0.7);
+  font-size: 0.8125rem;
+  font-weight: 500;
+  padding: 5px $sp3;
+  border-radius: 4px;
+  border: 1px solid rgba(255,255,255,0.2);
+  white-space: nowrap;
+  transition: all 0.15s;
+  &:hover {
+    color: #fff;
+    border-color: rgba(255,255,255,0.5);
+    background: rgba(255,255,255,0.1);
+    text-decoration: none;
+  }
+}
+
+.mobile-menu-btn {
+  display: none;
+  background: none;
+  border: 1px solid rgba(255,255,255,0.3);
+  color: #fff;
+  padding: 5px 9px;
+  border-radius: 4px;
+  cursor: pointer;
+  font-size: 1.05rem;
+  line-height: 1;
+  &:hover { background: rgba(255,255,255,0.1); }
+}
+
+// ── Page body ──────────────────────────────────────────
+.page-body {
+  display: flex;
+  flex: 1;
+  padding-top: $header-height;
+}
+
+// ── Sidebar ────────────────────────────────────────────
+.sidebar {
+  position: fixed;
+  top: $header-height; left: 0; bottom: 0;
+  width: $sidebar-width;
+  background: $sidebar-bg;
+  border-right: 1px solid $sidebar-border;
+  overflow-y: auto;
+  overflow-x: hidden;
+  z-index: 100;
+
+  &::-webkit-scrollbar { width: 4px; }
+  &::-webkit-scrollbar-track { background: transparent; }
+  &::-webkit-scrollbar-thumb { background: $border-color; border-radius: 2px; }
+}
+
+.sidebar-inner { padding: $sp4 0 $sp6; }
+
+.sidebar-overlay {
+  display: none;
+  position: fixed;
+  inset: 0;
+  background: rgba(0,0,0,0.4);
+  z-index: 99;
+}
+
+// ── Main content ───────────────────────────────────────
+.content {
+  margin-left: $sidebar-width;
+  flex: 1;
+  min-width: 0;
+}
+
+.content-inner {
+  max-width: $content-max-width;
+  padding: $sp6;
+}
+
+// ── Footer ─────────────────────────────────────────────
+.site-footer {
+  background: $solr-dark;
+  color: rgba(255,255,255,0.6);
+  padding: $sp5 $sp6;
+  font-size: 0.875rem;
+  line-height: 1.7;
+  margin-left: $sidebar-width;
+
+  a { color: rgba(255,255,255,0.75); &:hover { color: #fff; } }
+  p { margin-bottom: $sp2; &:last-child { margin-bottom: 0; } }
+}
+
+// ── Back to top ────────────────────────────────────────
+.back-to-top {
+  position: fixed;
+  bottom: $sp4; right: $sp4;
+  background: $solr-orange;
+  color: #fff;
+  border: none;
+  border-radius: 50%;
+  width: 40px; height: 40px;
+  cursor: pointer;
+  display: none;
+  align-items: center;
+  justify-content: center;
+  font-size: 1.1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
+  z-index: 500;
+  transition: background 0.15s;
+  &:hover { background: $solr-orange-dark; }
+  &.visible { display: flex; }
+}
diff --git a/docs/_sass/_nav.scss b/docs/_sass/_nav.scss
new file mode 100644
index 00000000..4b0bf3af
--- /dev/null
+++ b/docs/_sass/_nav.scss
@@ -0,0 +1,130 @@
+.nav-list {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+
+// ── Shared link/button style ───────────────────────────
+%nav-link-base {
+  display: flex;
+  align-items: center;
+  width: 100%;
+  padding: 6px $sp4;
+  font-family: $font-family;
+  font-size: 0.9375rem;
+  font-weight: 400;
+  color: $body-text;
+  text-decoration: none;
+  background: none;
+  border: none;
+  border-left: 3px solid transparent;
+  cursor: pointer;
+  text-align: left;
+  transition: color 0.15s, background 0.15s, border-color 0.15s;
+
+  &:hover {
+    color: $solr-orange;
+    background: rgba($solr-orange, 0.05);
+    border-left-color: rgba($solr-orange, 0.3);
+    text-decoration: none;
+  }
+}
+
+// ── Root-level items ───────────────────────────────────
+.nav-root-link { @extend %nav-link-base; }
+
+.nav-row {
+  display: flex;
+  align-items: stretch;
+
+  .nav-root-link {
+    flex: 1;
+    border-right: none;
+  }
+}
+
+.nav-toggle-btn {
+  @extend %nav-link-base;
+  flex: 0 0 auto;
+  width: 36px;
+  padding: 6px $sp2;
+  justify-content: center;
+  border-left: none;
+  color: $muted-text;
+  font-size: 0.65rem;
+
+  &:hover { color: $solr-orange; background: rgba($solr-orange, 0.05); }
+
+  .caret {
+    display: inline-block;
+    transition: transform 0.2s;
+  }
+
+  &.open .caret { transform: rotate(90deg); }
+}
+
+// Active state for root items
+.nav-item.active {
+  > .nav-root-link,
+  > .nav-row > .nav-root-link {
+    color: $solr-orange;
+    font-weight: 600;
+    background: rgba($solr-orange, 0.07);
+    border-left-color: $solr-orange;
+  }
+  > .nav-row > .nav-toggle-btn {
+    color: $solr-orange;
+  }
+}
+
+// ── Level-1 children ───────────────────────────────────
+.nav-children {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  display: none;
+  &.open { display: block; }
+
+  .nav-item > .nav-child-link {
+    @extend %nav-link-base;
+    padding-left: calc(#{$sp4} + 14px);
+    font-size: 0.9rem;
+  }
+
+  .nav-item.active > .nav-child-link {
+    color: $solr-orange;
+    font-weight: 600;
+    background: rgba($solr-orange, 0.07);
+    border-left-color: $solr-orange;
+  }
+
+  .nav-row .nav-child-link {
+    @extend %nav-link-base;
+    padding-left: calc(#{$sp4} + 14px);
+    font-size: 0.9rem;
+    flex: 1;
+  }
+}
+
+// ── Level-2 grandchildren ──────────────────────────────
+.nav-grandchildren {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  display: none;
+  &.open { display: block; }
+
+  .nav-item > .nav-gc-link {
+    @extend %nav-link-base;
+    padding-left: calc(#{$sp4} + 28px);
+    font-size: 0.875rem;
+    color: $muted-text;
+  }
+
+  .nav-item.active > .nav-gc-link {
+    color: $solr-orange;
+    font-weight: 600;
+    background: rgba($solr-orange, 0.06);
+    border-left-color: $solr-orange;
+  }
+}
diff --git a/docs/_sass/_responsive.scss b/docs/_sass/_responsive.scss
new file mode 100644
index 00000000..c4379d44
--- /dev/null
+++ b/docs/_sass/_responsive.scss
@@ -0,0 +1,33 @@
+@media (max-width: #{$bp-mobile}) {
+  .mobile-menu-btn { display: block; }
+  .header-links    { display: none; }
+
+  .search-wrap { max-width: 180px; }
+
+  .sidebar {
+    transform: translateX(-100%);
+    transition: transform 0.28s ease;
+    z-index: 200;
+    &.open { transform: translateX(0); }
+  }
+
+  .sidebar-overlay {
+    &.open { display: block; }
+  }
+
+  .content { margin-left: 0; }
+  .content-inner { padding: $sp4 $sp3; }
+
+  .site-footer { margin-left: 0; padding: $sp4 $sp3; }
+
+  h1 { font-size: 1.5rem; }
+  h2 { font-size: 1.2rem; }
+
+  table {
+    display: block;
+    overflow-x: auto;
+    -webkit-overflow-scrolling: touch;
+  }
+
+  .back-to-top { bottom: $sp3; right: $sp3; }
+}
diff --git a/docs/_sass/_search.scss b/docs/_sass/_search.scss
new file mode 100644
index 00000000..48637d6d
--- /dev/null
+++ b/docs/_sass/_search.scss
@@ -0,0 +1,61 @@
+.search-wrap {
+  position: relative;
+  flex: 1;
+  max-width: 340px;
+}
+
+.search-input {
+  width: 100%;
+  height: 32px;
+  padding: 0 $sp3 0 30px;
+  border: 1px solid rgba(255,255,255,0.2);
+  border-radius: 5px;
+  background: rgba(255,255,255,0.1);
+  background-image: url("data:image/svg+xml,%3Csvg 
xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' 
fill='none' stroke='rgba(255,255,255,0.55)' stroke-width='2.5' 
stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' 
r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
+  background-repeat: no-repeat;
+  background-position: 9px center;
+  color: #fff;
+  font-family: $font-family;
+  font-size: 0.875rem;
+  outline: none;
+  transition: border-color 0.15s, background-color 0.15s;
+
+  &::placeholder { color: rgba(255,255,255,0.4); }
+  &:focus { border-color: rgba(255,255,255,0.45); background-color: 
rgba(255,255,255,0.15); }
+}
+
+.search-results {
+  display: none;
+  position: absolute;
+  top: calc(100% + 6px);
+  left: 0; right: 0;
+  background: #fff;
+  border: 1px solid $border-color;
+  border-radius: 6px;
+  box-shadow: 0 8px 28px rgba(0,0,0,0.18);
+  max-height: 380px;
+  overflow-y: auto;
+  z-index: 2000;
+  &.open { display: block; }
+}
+
+.search-result {
+  display: block;
+  padding: $sp3 $sp4;
+  border-bottom: 1px solid $border-color;
+  text-decoration: none;
+  color: $body-text;
+  &:last-child { border-bottom: none; }
+  &:hover { background: $bg-alt; text-decoration: none; }
+
+  .result-title { font-weight: 600; font-size: 0.9375rem; color: $solr-dark; }
+  .result-path  { font-size: 0.8rem; color: $muted-text; margin-top: 2px; }
+  &:hover .result-title { color: $solr-orange; }
+}
+
+.search-no-results {
+  padding: $sp4;
+  text-align: center;
+  font-size: 0.9rem;
+  color: $muted-text;
+}
diff --git a/docs/_sass/_variables.scss b/docs/_sass/_variables.scss
new file mode 100644
index 00000000..20c3ca65
--- /dev/null
+++ b/docs/_sass/_variables.scss
@@ -0,0 +1,50 @@
+// Solr Brand Colors (from Solr Style Guide)
+$solr-orange:       #D9411E;
+$solr-dark:         #262130;
+$solr-dark-alt:     #25202f;
+$solr-orange-hover: #ff833d;
+$solr-orange-dark:  #A13016;
+
+// UI Colors
+$body-text:     #333333;
+$muted-text:    #666666;
+$border-color:  #d1d3d4;
+$background:    #ffffff;
+$bg-alt:        #f9f8f8;
+$code-bg:       #f4f4f4;
+$code-text:     #4F504D;
+
+// Callout Colors
+$note-border:     #305CB3;
+$note-bg:         #eef3ff;
+$note-label:      #1d3a80;
+$warning-border:  #e6a817;
+$warning-bg:      #fffbee;
+$warning-label:   #7a5800;
+$important-border: #D9411E;
+$important-bg:    #fff0ee;
+$important-label: #8b1a0a;
+
+// Typography
+$font-family: 'Raleway', 'Helvetica Neue', Arial, sans-serif;
+$font-mono:   Menlo, Consolas, 'Liberation Mono', Courier, monospace;
+$base-font-size:   16px;
+$base-line-height: 1.65;
+
+// Layout
+$header-height:    60px;
+$sidebar-width:    272px;
+$content-max-width: 900px;
+$sidebar-bg:       #f9f8f8;
+$sidebar-border:   #e4e2dd;
+
+// Spacing scale
+$sp1: 4px;
+$sp2: 8px;
+$sp3: 16px;
+$sp4: 24px;
+$sp5: 32px;
+$sp6: 48px;
+
+// Breakpoints
+$bp-mobile: 768px;
diff --git a/docs/assets/css/main.scss b/docs/assets/css/main.scss
new file mode 100644
index 00000000..4609056e
--- /dev/null
+++ b/docs/assets/css/main.scss
@@ -0,0 +1,10 @@
+---
+---
+@import "variables";
+@import "base";
+@import "layout";
+@import "nav";
+@import "content";
+@import "callouts";
+@import "search";
+@import "responsive";
diff --git a/docs/assets/images/solr-logo.svg b/docs/assets/images/solr-logo.svg
new file mode 100644
index 00000000..ba12b73e
--- /dev/null
+++ b/docs/assets/images/solr-logo.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 
6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; x="0px" y="0px"
+        viewBox="0 0 207.3 107.8" enable-background="new 0 0 207.3 107.8" 
xml:space="preserve">
+<g>
+       <path fill="#FFFFFF" 
d="M43.1,73.3c-2.3-1.2-5-2.1-7.9-2.6c-2.8-0.5-5.7-0.7-8.6-0.7c-2.3,0-4.7-0.2-7-0.6
+               
c-2.3-0.4-4.3-1.1-6.1-2.1c-1.7-1-3.2-2.4-4.3-4.1c-1.1-1.7-1.6-4-1.6-6.7C7.8,54,8.3,52,9.4,50.3c1.1-1.7,2.5-3.1,4.1-4.1
+               
c1.7-1,3.7-1.8,5.9-2.3c3.8-0.8,7.7-0.9,11.7-0.4c1.6,0.2,3.1,0.6,4.6,1.2c1.5,0.5,2.9,1.3,4.1,2.2c1.2,0.9,2.3,2.1,3.2,3.4
+               
l0.5,0.8l3.8-1.6l-0.8-1.1c-1-1.5-2.2-2.8-3.4-3.9c-1.2-1.2-2.7-2.1-4.4-2.9c-1.6-0.8-3.5-1.4-5.5-1.8c-2-0.4-4.4-0.6-7-0.6
+               
c-2.5,0-5.1,0.3-7.7,0.9c-2.6,0.6-5.1,1.5-7.3,2.8c-2.2,1.3-4.1,3.1-5.5,5.3c-1.4,2.2-2.1,5-2.1,8.1c0,3.3,0.7,6.2,2,8.4
+               
c1.3,2.3,3.1,4.1,5.2,5.4c2.1,1.3,4.6,2.3,7.3,2.8c2.7,0.5,5.5,0.8,8.4,0.8c2.3,0,4.7,0.2,7.2,0.5c2.4,0.3,4.7,1,6.7,2
+               
c2,1,3.6,2.3,4.9,4c1.2,1.6,1.8,3.8,1.8,6.6c0,2.4-0.6,4.5-1.8,6.2c-1.2,1.7-2.8,3.1-4.7,4.2c-1.9,1.1-4.1,1.9-6.5,2.4
+               
c-2.4,0.5-4.8,0.8-7.1,0.8c-3.9,0-7.7-0.7-11.4-2.2c-3.7-1.5-6.9-3.6-9.6-6.5l-0.7-0.8l-3,2.6l0.8,0.8c2.7,2.7,6.1,5.1,10,7
+               
c4,2,8.7,3,13.9,3c2.5,0,5.2-0.3,7.9-0.9c2.8-0.6,5.4-1.6,7.8-2.9c2.4-1.4,4.4-3.2,6-5.4c1.6-2.3,2.4-5.1,2.4-8.4
+               c0-3.4-0.8-6.2-2.2-8.5C47.4,76.3,45.5,74.6,43.1,73.3z"/>
+       <path fill="#FFFFFF" 
d="M95.3,63.7c-2-2.3-4.4-4.2-7.2-5.7c-2.8-1.5-6-2.2-9.4-2.2c-3.1,0-6.1,0.7-8.9,2c-2.7,1.3-5.2,3.1-7.2,5.4
+               
c-2,2.2-3.7,4.9-4.9,7.9c-1.2,3-1.8,6.2-1.8,9.4c0,3.1,0.6,6.1,1.6,9c1.1,2.9,2.6,5.5,4.6,7.8c2,2.3,4.4,4.2,7.2,5.6
+               
c2.8,1.4,5.9,2.2,9.3,2.2h0h0c3.2-0.1,6.2-0.8,9-2.1c2.7-1.3,5.2-3.2,7.2-5.4c2-2.2,3.7-4.9,4.8-7.8c1.2-2.9,1.7-6,1.7-9.3
+               c0-2.9-0.5-5.9-1.6-8.8C98.8,68.7,97.3,66,95.3,63.7z 
M78.7,101.1c-2.7,0-5.2-0.6-7.4-1.7c-2.2-1.1-4.2-2.7-5.8-4.6
+               
c-1.7-1.9-3-4.1-3.9-6.6c-0.9-2.5-1.5-5.1-1.6-7.8c0-2.4,0.4-4.9,1.3-7.4c0.9-2.5,2.2-4.7,3.8-6.7c1.7-2,3.7-3.6,6-4.8
+               
c2.3-1.2,4.8-1.8,7.6-1.8c2.6,0,5.1,0.6,7.3,1.7c2.3,1.2,4.3,2.7,6,4.6c1.7,1.9,3,4.1,4,6.6c1,2.5,1.5,5.1,1.5,7.7
+               
c0,2.4-0.4,4.9-1.3,7.4c-0.9,2.5-2.2,4.7-3.8,6.7c-1.7,2-3.7,3.6-6,4.8C84.1,100.5,81.5,101.1,78.7,101.1z"/>
+       <path fill="#FFFFFF" 
d="M122.1,100c-0.7,0.2-1.3,0.3-1.8,0.4c-0.5,0.1-1.1,0.2-1.7,0.3c-0.6,0.1-1.1,0.1-1.6,0.1
+               
c-1.3,0-2.3-0.4-3-1.4c-0.8-1-1.1-2-1.1-3V38h-4v58.3c0,2.2,0.7,4.1,2.1,5.8c1.4,1.7,3.4,2.5,6,2.5c0.8,0,1.6,0,2.4-0.1
+               
c0.7-0.1,1.4-0.2,2-0.3c0.6-0.1,1.3-0.2,2.1-0.4l1.4-0.3l-1.8-3.7L122.1,100z"/>
+       <path fill="#FFFFFF" 
d="M139.3,59.8c-2.1,1.5-3.9,3.3-5.5,5.5v-8.8h-4v47.7h4V74.5c0.6-1.9,1.3-3.8,2.3-5.4c1-1.7,2.1-3.1,3.5-4.4
+               
c1.4-1.2,3-2.2,4.8-3c1.8-0.7,3.8-1.2,6-1.3l1.1-0.1v-3.9h-1.1C146.2,56.5,142.4,57.6,139.3,59.8z"/>
+</g>
+<g>
+       <path fill="#262130" 
d="M196.2,13l-33,35.7l41.5-19.1C203.5,23.2,200.5,17.5,196.2,13z"/>
+       <path fill="#262130" 
d="M171.7,2.4c-4.6,0-8.9,0.9-12.9,2.6l-4.4,37.3l22.1-39.5C175,2.5,173.4,2.4,171.7,2.4z"/>
+       <path fill="#262130" 
d="M205,31.6l-39.3,22l36.9-4.4c1.7-4.1,2.7-8.5,2.7-13.2C205.3,34.5,205.2,33,205,31.6z"/>
+       <path fill="#262130" 
d="M190.5,63.8c4.4-3,8-7,10.6-11.6L166.6,59L190.5,63.8z"/>
+       <path fill="#262130" 
d="M178.6,3.1l-19.2,41.7l35.7-33C190.5,7.5,184.9,4.4,178.6,3.1z"/>
+       <path fill="#262130" 
d="M174.6,69.4c3.7-0.3,7.3-1.2,10.5-2.6l-19.4-2.3L174.6,69.4z"/>
+       <path fill="#262130" 
d="M141.1,22.2c-1.5,3.3-2.5,7-2.8,10.8l5.2,9.3L141.1,22.2z"/>
+       <path fill="#262130" 
d="M155.9,6.3c-4.7,2.5-8.8,6.2-11.8,10.6l4.9,24.5L155.9,6.3z"/>
+</g>
+</svg>
diff --git a/docs/assets/js/app.js b/docs/assets/js/app.js
new file mode 100644
index 00000000..47133c6f
--- /dev/null
+++ b/docs/assets/js/app.js
@@ -0,0 +1,136 @@
+(function () {
+  'use strict';
+
+  // ── Sidebar toggle buttons (expand/collapse) ──────────
+  document.querySelectorAll('.nav-toggle-btn').forEach(function (btn) {
+    btn.addEventListener('click', function (e) {
+      e.preventDefault();
+      var isOpen = btn.classList.toggle('open');
+      var list = btn.closest('.nav-row')
+        ? btn.closest('.nav-row').nextElementSibling
+        : btn.nextElementSibling;
+      if (list) list.classList.toggle('open', isOpen);
+    });
+  });
+
+  // ── Mobile sidebar ────────────────────────────────────
+  var menuBtn  = document.getElementById('mobile-menu-btn');
+  var sidebar  = document.getElementById('sidebar');
+  var overlay  = document.getElementById('sidebar-overlay');
+
+  function openSidebar() {
+    sidebar.classList.add('open');
+    overlay.classList.add('open');
+    menuBtn.setAttribute('aria-expanded', 'true');
+    document.body.style.overflow = 'hidden';
+  }
+
+  function closeSidebar() {
+    sidebar.classList.remove('open');
+    overlay.classList.remove('open');
+    menuBtn.setAttribute('aria-expanded', 'false');
+    document.body.style.overflow = '';
+  }
+
+  if (menuBtn) {
+    menuBtn.addEventListener('click', function () {
+      sidebar.classList.contains('open') ? closeSidebar() : openSidebar();
+    });
+  }
+  if (overlay) {
+    overlay.addEventListener('click', closeSidebar);
+  }
+
+  // ── Back to top ───────────────────────────────────────
+  var backBtn = document.getElementById('back-to-top');
+  if (backBtn) {
+    window.addEventListener('scroll', function () {
+      backBtn.classList.toggle('visible', window.scrollY > 400);
+    }, { passive: true });
+    backBtn.addEventListener('click', function () {
+      window.scrollTo({ top: 0, behavior: 'smooth' });
+    });
+  }
+
+  // ── Client-side search ────────────────────────────────
+  var searchInput   = document.getElementById('search-input');
+  var searchResults = document.getElementById('search-results');
+  var searchData    = null;
+
+  function loadSearchData(cb) {
+    if (searchData) { cb(); return; }
+    var base = document.querySelector('base') ? 
document.querySelector('base').href : '';
+    // Derive the baseurl from a known asset link
+    var cssLink = document.querySelector('link[rel=stylesheet]');
+    var baseurl = '';
+    if (cssLink) {
+      var m = cssLink.getAttribute('href').match(/^(.*?)\/assets\/css\//);
+      if (m) baseurl = m[1];
+    }
+    fetch(baseurl + '/search.json')
+      .then(function (r) { return r.json(); })
+      .then(function (data) { searchData = data; cb(); })
+      .catch(function () { searchData = []; });
+  }
+
+  function renderResults(query) {
+    if (!query || query.length < 2) {
+      searchResults.classList.remove('open');
+      return;
+    }
+    var q = query.toLowerCase();
+    var matches = searchData.filter(function (p) {
+      return p.title.toLowerCase().indexOf(q) !== -1 ||
+             (p.content && p.content.toLowerCase().indexOf(q) !== -1);
+    }).slice(0, 10);
+
+    if (matches.length === 0) {
+      searchResults.innerHTML = '<div class="search-no-results">No results for 
"' +
+        query.replace(/</g, '&lt;') + '"</div>';
+    } else {
+      searchResults.innerHTML = matches.map(function (p) {
+        return '<a class="search-result" href="' + p.url + '">' +
+          '<div class="result-title">' + p.title + '</div>' +
+          '<div class="result-path">' + p.url + '</div>' +
+          '</a>';
+      }).join('');
+    }
+    searchResults.classList.add('open');
+  }
+
+  if (searchInput) {
+    searchInput.addEventListener('input', function () {
+      var query = searchInput.value.trim();
+      if (!query) { searchResults.classList.remove('open'); return; }
+      loadSearchData(function () { renderResults(query); });
+    });
+
+    searchInput.addEventListener('focus', function () {
+      if (searchInput.value.trim().length >= 2 && searchData) {
+        renderResults(searchInput.value.trim());
+      }
+    });
+
+    document.addEventListener('click', function (e) {
+      if (!searchInput.contains(e.target) && 
!searchResults.contains(e.target)) {
+        searchResults.classList.remove('open');
+      }
+    });
+
+    document.addEventListener('keydown', function (e) {
+      if (e.key === 'Escape') searchResults.classList.remove('open');
+    });
+  }
+
+  // ── Heading anchor links ──────────────────────────────
+  document.querySelectorAll('.page-content h2, .page-content h3, .page-content 
h4').forEach(function (h) {
+    if (!h.id) return;
+    var a = document.createElement('a');
+    a.className = 'heading-anchor';
+    a.href = '#' + h.id;
+    a.setAttribute('aria-label', 'Link to ' + h.textContent);
+    a.innerHTML = '#';
+    h.appendChild(a);
+  });
+
+}());
diff --git a/docs/search.json b/docs/search.json
new file mode 100644
index 00000000..5ffcac24
--- /dev/null
+++ b/docs/search.json
@@ -0,0 +1,6 @@
+---
+layout: none
+---
+[{% assign first = true %}{% for p in site.pages %}{% if p.nav_order %}{% 
unless first %},{% endunless %}{% assign first = false %}
+{"title":{{ p.title | jsonify }},"url":{{ p.url | relative_url | jsonify 
}},"content":{{ p.content | strip_html | normalize_whitespace | truncate: 500 | 
jsonify }}}{% endif %}{% endfor %}
+]


Reply via email to