Fix file view display and make nav crumbs optional
Arborium defines --arb-bg-light on :root; overriding it on
.code-surface beats the theme background without JS or specificity fights.

Assisted-by: Claude Sonnet 4.6 via Claude Code
change nopqqnmkxrzkrtmtpwtvurqkzltuyxps
commit 58384c5051a9bab068cbcc921cf00da5c9d21aaf
author Alpha Chen <alpha@kejadlen.dev>
date
parent rzuuzvmx
diff --git a/quire-server/src/quire/web/handlers/ci.rs b/quire-server/src/quire/web/handlers/ci.rs
index ec35274..5a5a419 100644
--- a/quire-server/src/quire/web/handlers/ci.rs
+++ b/quire-server/src/quire/web/handlers/ci.rs
@@ -6,7 +6,7 @@ use axum::response::{IntoResponse, Response};
 
 use super::super::db;
 use super::super::templates::{
-    Crumb, DetailJob, DetailRun, DetailShEvent, RunDetailTemplate, RunListRow, RunListTemplate,
+    DetailJob, DetailRun, DetailShEvent, RunDetailTemplate, RunListRow, RunListTemplate,
     nav_sections,
 };
 use super::git::RepoView;
@@ -64,7 +64,7 @@ pub async fn run_list(RunListPath { repo }: RunListPath, State(quire): State<Qui
     let tmpl = RunListTemplate {
         sections: nav_sections(&repo_display, "ci", true),
         repo: repo_display,
-        crumbs: vec![],
+        crumbs: None,
         runs: template_runs,
         bookmarks,
         tags,
@@ -207,14 +207,10 @@ pub async fn run_detail(
     let quire_ci_log = quire_ci_log_handle.await.unwrap_or_default();
     let (bookmarks, tags) = refs_handle.await.unwrap_or_default();
 
-    let crumbs = vec![
-        Crumb::with_href("ci", format!("/{}/ci", repo_display)),
-        Crumb::new(detail_run.sha_short()),
-    ];
     let tmpl = RunDetailTemplate {
         sections: nav_sections(&repo_display, "ci", true),
         repo: repo_display,
-        crumbs,
+        crumbs: None,
         run: detail_run,
         jobs: detail_jobs,
         quire_ci_log,
diff --git a/quire-server/src/quire/web/handlers/commit.rs b/quire-server/src/quire/web/handlers/commit.rs
index 13cb9ee..b340b4b 100644
--- a/quire-server/src/quire/web/handlers/commit.rs
+++ b/quire-server/src/quire/web/handlers/commit.rs
@@ -5,7 +5,7 @@ use axum::http::StatusCode;
 use axum::response::IntoResponse;
 use axum::response::Response;
 
-use super::super::templates::{CommitParent, CommitTemplate, Crumb, nav_sections};
+use super::super::templates::{CommitParent, CommitTemplate, nav_sections};
 use super::git::RepoView;
 use super::render;
 use crate::Quire;
@@ -104,11 +104,10 @@ pub async fn commit_view(
         sha.clone()
     };
 
-    let crumbs = vec![Crumb::with_href("log", format!("/{repo_display}/log"))];
     let tmpl = CommitTemplate {
         sections: nav_sections(&repo_display, "log", auth.is_authenticated()),
         repo: repo_display,
-        crumbs,
+        crumbs: None,
         sha: sha.clone(),
         sha_short,
         sha_head: sha[..sha.len().min(4)].to_string(),
diff --git a/quire-server/src/quire/web/handlers/log_view.rs b/quire-server/src/quire/web/handlers/log_view.rs
index 9f21e8e..a34eecb 100644
--- a/quire-server/src/quire/web/handlers/log_view.rs
+++ b/quire-server/src/quire/web/handlers/log_view.rs
@@ -5,7 +5,7 @@ use axum::http::StatusCode;
 use axum::response::IntoResponse;
 use axum::response::Response;
 
-use super::super::templates::{Crumb, LogTemplate, nav_sections};
+use super::super::templates::{LogTemplate, nav_sections};
 use super::git::RepoView;
 use super::render;
 use crate::Quire;
@@ -38,11 +38,10 @@ pub async fn log_view(
     .await
     .unwrap_or_default();
 
-    let crumbs = vec![Crumb::new("log")];
     let tmpl = LogTemplate {
         sections: nav_sections(&repo_display, "log", auth.is_authenticated()),
         repo: repo_display,
-        crumbs,
+        crumbs: None,
         changes,
         bookmark,
         sha_short,
diff --git a/quire-server/src/quire/web/handlers/mod.rs b/quire-server/src/quire/web/handlers/mod.rs
index 33328fb..6a2c2d0 100644
--- a/quire-server/src/quire/web/handlers/mod.rs
+++ b/quire-server/src/quire/web/handlers/mod.rs
@@ -22,7 +22,7 @@ use axum::extract::State;
 use axum::http::{StatusCode, header};
 use axum::response::{Html, IntoResponse, Response};
 
-use super::templates::{ConfigTemplate, Crumb, ErrorTemplate};
+use super::templates::{ConfigTemplate, ErrorTemplate};
 use crate::Quire;
 
 /// Render a template into an HTML response, returning 500 on render failure.
@@ -49,7 +49,7 @@ pub(super) fn render_error(
 ) -> Response {
     let tmpl = ErrorTemplate {
         repo,
-        crumbs: vec![Crumb::new("error")],
+        crumbs: None,
         title: title.to_string(),
         detail: detail.clone(),
     };
@@ -76,7 +76,7 @@ pub async fn stylesheet() -> Response {
 
 pub async fn config(State(quire): State<Quire>) -> Response {
     let tmpl = ConfigTemplate {
-        crumbs: vec![Crumb::new("config")],
+        crumbs: None,
         config: quire.config.clone(),
     };
     render(&tmpl)
diff --git a/quire-server/src/quire/web/handlers/refs.rs b/quire-server/src/quire/web/handlers/refs.rs
index aa0da89..7b26618 100644
--- a/quire-server/src/quire/web/handlers/refs.rs
+++ b/quire-server/src/quire/web/handlers/refs.rs
@@ -5,7 +5,7 @@ use axum::http::StatusCode;
 use axum::response::IntoResponse;
 use axum::response::Response;
 
-use super::super::templates::{BookmarksTemplate, Crumb, TagsTemplate, nav_sections};
+use super::super::templates::{BookmarksTemplate, TagsTemplate, nav_sections};
 use super::git::RepoView;
 use super::render;
 use crate::Quire;
@@ -30,11 +30,10 @@ pub async fn bookmarks_view(
     .await
     .unwrap_or_default();
 
-    let crumbs = vec![Crumb::new("bookmarks")];
     let tmpl = BookmarksTemplate {
         sections: nav_sections(&repo_display, "bookmarks", auth.is_authenticated()),
         repo: repo_display,
-        crumbs,
+        crumbs: None,
         bookmarks,
         tags,
     };
@@ -60,11 +59,10 @@ pub async fn tags_view(
     .await
     .unwrap_or_default();
 
-    let crumbs = vec![Crumb::new("tags")];
     let tmpl = TagsTemplate {
         sections: nav_sections(&repo_display, "tags", auth.is_authenticated()),
         repo: repo_display,
-        crumbs,
+        crumbs: None,
         bookmarks,
         tags,
     };
diff --git a/quire-server/src/quire/web/handlers/repo.rs b/quire-server/src/quire/web/handlers/repo.rs
index 256df98..571747c 100644
--- a/quire-server/src/quire/web/handlers/repo.rs
+++ b/quire-server/src/quire/web/handlers/repo.rs
@@ -61,7 +61,7 @@ pub async fn repo_home(
     let tmpl = RepoHomeTemplate {
         sections: nav_sections(&repo_display, "overview", auth.is_authenticated()),
         repo: repo_display,
-        crumbs: vec![],
+        crumbs: None,
         head,
         readme_html,
         bookmarks,
diff --git a/quire-server/src/quire/web/handlers/tree.rs b/quire-server/src/quire/web/handlers/tree.rs
index c7344ba..c478731 100644
--- a/quire-server/src/quire/web/handlers/tree.rs
+++ b/quire-server/src/quire/web/handlers/tree.rs
@@ -63,7 +63,7 @@ async fn tree_or_file_at_path(quire: Quire, repo: String, path: String, authed:
             let tmpl = TreeTemplate {
                 sections: nav_sections(&repo_display, "tree", authed),
                 repo: repo_display,
-                crumbs,
+                crumbs: Some(crumbs),
                 bookmarks,
                 tags,
                 path,
@@ -80,7 +80,7 @@ async fn tree_or_file_at_path(quire: Quire, repo: String, path: String, authed:
             let tmpl = FileViewTemplate {
                 sections: nav_sections(&repo_display, "tree", authed),
                 repo: repo_display.clone(),
-                crumbs,
+                crumbs: Some(crumbs),
                 path,
                 bookmark: file_data.bookmark,
                 sha_short: file_data.sha_short.clone(),
@@ -229,7 +229,7 @@ struct FileData {
 }
 
 fn build_file_crumbs(repo: &str, path: &str) -> Vec<Crumb> {
-    let mut crumbs = vec![Crumb::with_href("tree", format!("/{repo}/tree"))];
+    let mut crumbs = vec![];
     if path.is_empty() {
         return crumbs;
     }
diff --git a/quire-server/src/quire/web/templates.rs b/quire-server/src/quire/web/templates.rs
index b386b8a..48ee17e 100644
--- a/quire-server/src/quire/web/templates.rs
+++ b/quire-server/src/quire/web/templates.rs
@@ -78,7 +78,7 @@ impl Crumb {
 #[template(path = "ci/run_list.html")]
 pub struct RunListTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub runs: Vec<RunListRow>,
     pub bookmarks: Vec<BookmarkRow>,
     pub tags: Vec<TagRow>,
@@ -137,7 +137,7 @@ impl RunListRow {
 #[template(path = "ci/run_detail.html")]
 pub struct RunDetailTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub run: DetailRun,
     pub jobs: Vec<DetailJob>,
     pub quire_ci_log: String,
@@ -297,7 +297,7 @@ pub struct ListedRepo {
 #[template(path = "repo_home.html")]
 pub struct RepoHomeTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub head: Option<HeadInfo>,
     pub readme_html: Option<String>,
     pub bookmarks: Vec<BookmarkRow>,
@@ -407,7 +407,7 @@ impl ChangeRow {
 #[derive(Template)]
 #[template(path = "config.html")]
 pub struct ConfigTemplate {
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub config: crate::GlobalConfig,
 }
 
@@ -429,7 +429,7 @@ impl ConfigTemplate {
 #[template(path = "tree.html")]
 pub struct TreeTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub bookmarks: Vec<BookmarkRow>,
     pub tags: Vec<TagRow>,
     pub sections: Vec<SectionLink>,
@@ -530,7 +530,7 @@ impl TreeEntry {
 #[template(path = "commit.html")]
 pub struct CommitTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub sections: Vec<SectionLink>,
     pub sha: String,
     pub sha_short: String,
@@ -578,7 +578,7 @@ impl CommitParent {
 #[template(path = "log.html")]
 pub struct LogTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub sections: Vec<SectionLink>,
     pub changes: Vec<ChangeRow>,
     pub bookmark: String,
@@ -606,7 +606,7 @@ impl LogTemplate {
 #[template(path = "bookmarks.html")]
 pub struct BookmarksTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub bookmarks: Vec<BookmarkRow>,
     pub tags: Vec<TagRow>,
     pub sections: Vec<SectionLink>,
@@ -624,7 +624,7 @@ impl BookmarksTemplate {
 #[template(path = "tags.html")]
 pub struct TagsTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub bookmarks: Vec<BookmarkRow>,
     pub tags: Vec<TagRow>,
     pub sections: Vec<SectionLink>,
@@ -642,7 +642,7 @@ impl TagsTemplate {
 #[template(path = "error.html")]
 pub struct ErrorTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub title: String,
     pub detail: String,
 }
@@ -659,7 +659,7 @@ impl ErrorTemplate {
 #[template(path = "file.html")]
 pub struct FileViewTemplate {
     pub repo: String,
-    pub crumbs: Vec<Crumb>,
+    pub crumbs: Option<Vec<Crumb>>,
     pub sections: Vec<SectionLink>,
     pub path: String,
     pub bookmark: String,
diff --git a/quire-server/static/style.css b/quire-server/static/style.css
index 4d1bf8f..7660119 100644
--- a/quire-server/static/style.css
+++ b/quire-server/static/style.css
@@ -796,7 +796,10 @@ html.dark {
   line-height: 1.7;
   display: grid;
   grid-template-columns: auto 1fr;
-  background: var(--code);
+  background: var(--bg);
+  /* Override arborium's theme background variables so they don't clash. */
+  --arb-bg-light: transparent;
+  --arb-bg-dark: transparent;
 }
 
 .code-gutter {
@@ -816,37 +819,21 @@ html.dark {
   padding: 16px 16px 16px 12px;
   overflow: auto;
   margin: 0;
-  white-space: pre;
+  white-space: pre-wrap;
+  word-break: break-word;
   font-family: inherit;
   font-size: inherit;
   line-height: inherit;
-  background: transparent !important;
-  border-radius: 0 !important;
-}
-
-.code-body > code[data-lang],
-.code-body > code[data-lang] * {
-  background: transparent !important;
+  background: var(--bg);
 }
 
 /* ── Arborium syntax highlighting integration ──────────────────── */
 
-/* Strip any background arborium injects on the code element or any wrapper it adds. */
-.code-body,
-.code-body * {
-  background: transparent !important;
-}
-
-/* Restore the code surface background on the pre itself. */
-.code-body {
-  background: var(--code) !important;
-}
-
 /* Left-rail accent only for standalone code blocks, not the file view grid. */
-:not(.code-body):has(code[class*="language-"]),
-:not(.code-body):has(code[data-lang]) {
+pre:not(.code-body):has(code[class*="language-"]),
+pre:not(.code-body):has(code[data-lang]) {
   border-left: 2px solid var(--accent) !important;
-  background: var(--code) !important;
+  background: var(--bg) !important;
   border-radius: 0 !important;
 }
 
diff --git a/quire-server/templates/_nav.html b/quire-server/templates/_nav.html
index 264773b..f91e7b8 100644
--- a/quire-server/templates/_nav.html
+++ b/quire-server/templates/_nav.html
@@ -10,8 +10,8 @@
       </svg>
 
     </a>
-    <span class="sep">/</span>
     <a class="nav-repo" href="/{{ repo }}">{{ repo }}</a>
+    {% if let Some(crumbs) = crumbs %}
     {% for crumb in crumbs %}
     <span class="sep">/</span>
     {% if let Some(href) = crumb.href %}
@@ -20,5 +20,6 @@
     <span class="nav-crumb">{{ crumb.label }}</span>
     {% endif %}
     {% endfor %}
+    {% endif %}
   </div>
 </nav>