-
-
-
-
{meta.label}
-
{meta.role}
-
-
-
{meta.data}
-
))}
+
+
+
+
+
+
MARKDOWN DOCUMENTATION
+
{doc ? doc.label : "No document selected"}
+
+
+
+ {doc ? `docs/${doc.rel}` : ""}
+
+
+ {doc ? (
+
+ ) : (
+
+ No documents
+ No markdown files were bundled with the dashboard.
+
+ )}
);
diff --git a/monitoring_ui/src/docs.js b/monitoring_ui/src/docs.js
new file mode 100644
index 0000000..14342d0
--- /dev/null
+++ b/monitoring_ui/src/docs.js
@@ -0,0 +1,41 @@
+const entries = import.meta.glob("../docs/**/*.md", {
+ as: "raw",
+ eager: true,
+});
+
+export const docsIndex = Object.entries(entries)
+ .map(([path, content]) => {
+ const rel = path.replace("../docs/", "");
+ const parts = rel.split("/");
+ const file = parts[parts.length - 1];
+ const group =
+ parts.length > 1 ? parts.slice(0, -1).join("/") : "(top level)";
+ return {
+ rel,
+ group,
+ file,
+ label: file.replace(/\.md$/, "").replace(/_/g, " "),
+ content,
+ };
+ })
+ .sort((a, b) => a.rel.localeCompare(b.rel));
+
+const groups = [...new Set(docsIndex.map((d) => d.group))];
+export const docGroups = [
+ "(top level)",
+ ...groups.filter((g) => g !== "(top level)").sort(),
+];
+
+export function resolveDocRel(fromRel, href) {
+ if (!href) return null;
+ const clean = href.split("#")[0] || "";
+ if (!clean.endsWith(".md")) return null;
+ const dirParts = fromRel.split("/").slice(0, -1);
+ for (const part of clean.split("/")) {
+ if (!part || part === ".") continue;
+ if (part === "..") dirParts.pop();
+ else dirParts.push(part);
+ }
+ const resolved = dirParts.join("/");
+ return docsIndex.some((d) => d.rel === resolved) ? resolved : null;
+}
\ No newline at end of file
diff --git a/monitoring_ui/src/styles.css b/monitoring_ui/src/styles.css
index cd26cfb..314e65b 100644
--- a/monitoring_ui/src/styles.css
+++ b/monitoring_ui/src/styles.css
@@ -647,72 +647,203 @@ textarea:focus {
.docs-panel {
min-height: 500px;
}
-.docs-grid {
+
+.docs-viewer {
display: grid;
- grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
- gap: 16px;
+ grid-template-columns: 280px 1fr;
+ min-height: 560px;
+ padding: 0;
+ overflow: hidden;
}
-.doc-card {
- background: rgba(23, 32, 34, 0.88);
- border: 1px solid var(--line);
- border-radius: 6px;
- padding: 20px;
- border-top: 2px solid var(--card-color);
+.docs-sidebar {
+ background: #141c1e;
+ border-right: 1px solid var(--line);
+ padding: 18px;
+ max-height: 74vh;
+ overflow-y: auto;
}
-.doc-card.amber { --card-color: var(--amber); }
-.doc-card.teal { --card-color: var(--mint); }
-.doc-card.blue { --card-color: var(--blue); }
-.doc-card.coral { --card-color: var(--coral); }
-.doc-header {
- display: flex;
- gap: 12px;
- align-items: start;
+.docs-search {
+ width: 100%;
+ padding: 8px 10px;
+ font-size: 12px;
+}
+.docs-group {
margin-bottom: 12px;
}
-.doc-header .service-dot {
- flex-shrink: 0;
- margin-top: 2px;
-}
-.doc-header strong { display: block; font-size: 14px; }
-.doc-header p { margin: 3px 0 0; color: var(--muted); font-size: 11px; }
-.doc-description {
+.docs-group-title {
+ font: 600 10px "DM Mono", monospace;
+ text-transform: uppercase;
+ letter-spacing: 0.12em;
color: var(--muted);
+ margin: 18px 0 6px;
+}
+.docs-group:first-child .docs-group-title {
+ margin-top: 0;
+}
+.docs-nav-item {
+ display: block;
+ width: 100%;
+ text-align: left;
+ background: transparent;
+ border: 0;
+ color: #c6d5d3;
font-size: 12px;
- line-height: 1.5;
- margin-bottom: 14px;
+ padding: 7px 9px;
+ border-radius: 4px;
+ cursor: pointer;
+ line-height: 1.3;
}
-.doc-links {
+.docs-nav-item:hover {
+ background: #1d282a;
+ color: var(--mint);
+}
+.docs-nav-item.active {
+ background: rgba(138, 232, 194, 0.12);
+ color: var(--mint);
+}
+.docs-nav-item small {
+ display: block;
+ color: var(--muted);
+ font: 10px "DM Mono", monospace;
+}
+.docs-content {
+ padding: 22px 28px 32px;
+ min-width: 0;
+ max-height: 74vh;
+ overflow-y: auto;
+}
+.docs-content-head {
display: flex;
- flex-direction: column;
- gap: 12px;
+ justify-content: space-between;
+ align-items: baseline;
+ gap: 14px;
+ flex-wrap: wrap;
+ margin-bottom: 10px;
}
-.doc-link {
+.docs-source {
+ font: 10px "DM Mono", monospace;
+ color: var(--muted);
+ white-space: nowrap;
+}
+.markdown-body {
+ color: #d3dddd;
+ font-size: 14px;
+ line-height: 1.65;
+ word-wrap: break-word;
+}
+.markdown-body h1,
+.markdown-body h2,
+.markdown-body h3,
+.markdown-body h4 {
+ color: #e7eeee;
+ letter-spacing: -0.02em;
+ margin: 1.5em 0 0.5em;
+ scroll-margin-top: 20px;
+}
+.markdown-body h1 {
+ font-size: 24px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid var(--line);
+}
+.markdown-body h2 {
+ font-size: 19px;
+}
+.markdown-body h3 {
+ font-size: 15px;
+}
+.markdown-body p {
+ margin: 0.7em 0;
+}
+.markdown-body a {
color: var(--mint);
text-decoration: none;
- font: 500 11px "DM Mono", monospace;
- display: inline-flex;
- align-items: center;
- gap: 6px;
}
-.doc-link:hover { text-decoration: underline; }
-.routes-detail summary {
- color: var(--muted);
- font: 500 10px "DM Mono", monospace;
- cursor: pointer;
- text-transform: uppercase;
+.markdown-body a:hover {
+ text-decoration: underline;
}
-.routes-detail ul {
- margin: 8px 0 0;
- padding-left: 18px;
- font-size: 11px;
- color: #c6d5d3;
+.markdown-body ul,
+.markdown-body ol {
+ padding-left: 22px;
+ margin: 0.7em 0;
}
-.routes-detail li { margin: 4px 0; }
-.routes-detail code {
- font: 11px "DM Mono", monospace;
+.markdown-body li {
+ margin: 0.32em 0;
+}
+.markdown-body li > ul,
+.markdown-body li > ol {
+ margin: 0.2em 0;
+}
+.markdown-body code {
+ font: 0.9em "DM Mono", monospace;
background: #111a1c;
- padding: 2px 4px;
- border-radius: 2px;
+ padding: 2px 5px;
+ border-radius: 3px;
+ color: var(--amber);
+}
+.markdown-body pre {
+ background: #0d1416;
+ border: 1px solid var(--line);
+ border-radius: 6px;
+ padding: 14px 16px;
+ overflow: auto;
+ line-height: 1.45;
+}
+.markdown-body pre code {
+ background: none;
+ padding: 0;
+ color: #d3dddd;
+ font-size: 12px;
+}
+.markdown-body blockquote {
+ margin: 1em 0;
+ padding: 0.6em 14px;
+ border-left: 3px solid var(--blue);
+ background: rgba(126, 183, 245, 0.06);
+ color: var(--muted);
+}
+.markdown-body table {
+ border-collapse: collapse;
+ width: 100%;
+ margin: 1em 0;
+ font-size: 13px;
+}
+.markdown-body th,
+.markdown-body td {
+ border: 1px solid var(--line);
+ padding: 8px 10px;
+ text-align: left;
+ vertical-align: top;
+}
+.markdown-body th {
+ background: #1a2527;
+ color: #e7eeee;
+ font-weight: 600;
+}
+.markdown-body hr {
+ border: 0;
+ border-top: 1px solid var(--line);
+ margin: 1.6em 0;
+}
+.markdown-body img {
+ max-width: 100%;
+ border-radius: 4px;
+}
+.markdown-body > :first-child {
+ margin-top: 0;
+}
+@media (max-width: 900px) {
+ .docs-viewer {
+ grid-template-columns: 1fr;
+ }
+ .docs-sidebar {
+ border-right: 0;
+ border-bottom: 1px solid var(--line);
+ max-height: 38vh;
+ }
+ .docs-content {
+ max-height: none;
+ padding: 20px;
+ }
}
@media (max-width: 700px) {