diff --git a/.forge/prs/85ade488-b55e-47b9-b58e-0dd9a911b8e3/patch.diff b/.forge/prs/85ade488-b55e-47b9-b58e-0dd9a911b8e3/patch.diffnew file mode 100644index 0000000..f22e818--- /dev/null+++ b/.forge/prs/85ade488-b55e-47b9-b58e-0dd9a911b8e3/patch.diff@@ -0,0 +1,192 @@1+From 64653f63c93f3a1cefe1fe1f6228c31bc511064d Mon Sep 17 00:00:00 20012+From: hu13-test <[email protected]>3+Date: Wed, 28 Oct 2026 10:52:36 +00004+Subject: [PATCH] use gf1 gl0w logo in header/footer lockup (#118)5+6+---7+ .../issue.md | 21 +++++++++++++++8+ src/build.rs | 2 ++9+ src/layout.rs | 8 +++---10+ src/logo.rs | 11 +++++---11+ static/gl0w.svg | 4 +++12+ static/style.css | 6 ++---13+ tests/brand.rs | 26 +++++++++++++++++--14+ 7 files changed, 67 insertions(+), 11 deletions(-)15+ create mode 100644 .forge/issues/d105f27f-f406-4fc7-a286-c331e45e2f5c/issue.md16+ create mode 100644 static/gl0w.svg17+18+diff --git a/.forge/issues/d105f27f-f406-4fc7-a286-c331e45e2f5c/issue.md b/.forge/issues/d105f27f-f406-4fc7-a286-c331e45e2f5c/issue.md19+new file mode 10064420+index 0000000..ddfcd2c21+--- /dev/null22++++ b/.forge/issues/d105f27f-f406-4fc7-a286-c331e45e2f5c/issue.md23+@@ -0,0 +1,21 @@24++---25++id: d105f27f-f406-4fc7-a286-c331e45e2f5c26++title: Use the gf1 gl0w logo in the header/footer lockup27++state: open28++labels:29++- area:render30++assignees: []31++milestone: null32++created: 2026-10-28T10:49:07.368617004Z33++updated: null34++---35++## Problem36++37++The #70 lockup still renders the gl0w brand as a monospace text placeholder (`gl0w` in a bordered box). The real gl0w mark is now available at `~/src/code/gf1/website/assets/logo.svg` (inverted-triangle G, `currentColor`).38++39++## Fix40++41++- Vendor the exact SVG as `static/gl0w.svg` and emit it in `dist/gl0w.svg`.42++- Inline the mark in the header lockup and footer brand so `currentColor` follows the dark/light theme and hover states.43++- Keep the hu13 diamond-hub logo and the `hu13 — a gl0w project` tagline.44++- Add a regression test for the gf1 viewBox/path geometry, the absence of the text placeholder, and the emitted asset.45+diff --git a/src/build.rs b/src/build.rs46+index a572829..ad80815 10064447+--- a/src/build.rs48++++ b/src/build.rs49+@@ -1379,6 +1379,8 @@ pub const HEADERS_FILE: &str = "\50+ fn write_favicon_and_manifest(out: &Path) -> Result<(), String> {51+ let logo = include_str!("../static/logo.svg");52+ std::fs::write(out.join("logo.svg"), logo).map_err(|e| format!("hu13: write logo.svg: {e}"))?;53++ let gl0w = include_str!("../static/gl0w.svg");54++ std::fs::write(out.join("gl0w.svg"), gl0w).map_err(|e| format!("hu13: write gl0w.svg: {e}"))?;55+ let icon = include_str!("../static/favicon.svg");56+ std::fs::write(out.join("favicon.svg"), icon)57+ .map_err(|e| format!("hu13: write favicon.svg: {e}"))?;58+diff --git a/src/layout.rs b/src/layout.rs59+index b2e29e5..339ec5e 10064460+--- a/src/layout.rs61++++ b/src/layout.rs62+@@ -329,7 +329,8 @@ pub fn provenance_footer(branch: Option<&str>, short_sha: Option<&str>) -> Strin63+ }64+ }65+ format!(66+- "<footer class=\"site-footer\"><div class=\"wrap\"><div class=\"footer-brand\"><a class=\"gl0w-mark\" href=\"https://gl0w.world\" rel=\"noopener\">gl0w</a><span class=\"footer-tag\">hu13 — a gl0w project</span></div><p class=\"footer-links\"><a href=\"https://gl0w.world\" rel=\"noopener\">gl0w.world</a><a href=\"/agents.html\">agents</a><a href=\"/new-issue.html\">submit</a></p><p class=\"muted footer-provenance\">{line}</p></div></footer>"67++ "<footer class=\"site-footer\"><div class=\"wrap\"><div class=\"footer-brand\"><a class=\"gl0w-mark\" href=\"https://gl0w.world\" rel=\"noopener\" aria-label=\"gl0w\">{gl0w}</a><span class=\"footer-tag\">hu13 — a gl0w project</span></div><p class=\"footer-links\"><a href=\"https://gl0w.world\" rel=\"noopener\">gl0w.world</a><a href=\"/agents.html\">agents</a><a href=\"/new-issue.html\">submit</a></p><p class=\"muted footer-provenance\">{line}</p></div></footer>",68++ gl0w = crate::logo::GL0W_SVG69+ )70+ }71+ 72+@@ -425,11 +426,12 @@ fn page_site_inner(73+ <html lang=\"en\">\n\74+ <head>\n{head}</head>\n\75+ <body>\n\76+-<header class=\"site-header\"><div class=\"wrap header-bar\"><a class=\"brand-lockup\" href=\"/\" aria-label=\"hu13 by gl0w — home\"><span class=\"gl0w-mark\" aria-hidden=\"true\">gl0w</span><span class=\"lockup-slash\" aria-hidden=\"true\">/</span><img class=\"site-logo\" src=\"/logo.svg\" alt=\"hu13 logo\" width=\"84\" height=\"28\"></a><span class=\"sep\" aria-hidden=\"true\">•</span><nav class=\"site-nav nav-scroll\" aria-label=\"Site\"><div class=\"nav-scroll-row\">{nav_active}</div></nav></div></header>\n\77++<header class=\"site-header\"><div class=\"wrap header-bar\"><a class=\"brand-lockup\" href=\"/\" aria-label=\"hu13 by gl0w — home\"><span class=\"gl0w-mark\" aria-hidden=\"true\">{gl0w}</span><span class=\"lockup-slash\" aria-hidden=\"true\">/</span><img class=\"site-logo\" src=\"/logo.svg\" alt=\"hu13 logo\" width=\"84\" height=\"28\"></a><span class=\"sep\" aria-hidden=\"true\">•</span><nav class=\"site-nav nav-scroll\" aria-label=\"Site\"><div class=\"nav-scroll-row\">{nav_active}</div></nav></div></header>\n\78+ <main class=\"wrap\">\n{body}\n</main>\n\79+ {footer}\n\80+ </body>\n\81+-</html>\n"82++</html>\n",83++ gl0w = crate::logo::GL0W_SVG84+ )85+ }86+ 87+diff --git a/src/logo.rs b/src/logo.rs88+index f71358c..9e34f14 10064489+--- a/src/logo.rs90++++ b/src/logo.rs91+@@ -8,9 +8,10 @@92+ //! the text banner lives in `static/ascii.txt` (owner block-art, 12 lines,93+ //! stripped from `static/logo-ansi.txt`).94+ //!95+-//! [`ASCII_ART`], [`LOGO_ANSI_RAW`], [`LOGO_SVG`], [`FAVICON_SVG`] and96+-//! [`WORDMARK_SVG`] re-expose those static files for later issues (navbar97+-//! #16, favicon #17, wiki README #19, agents page) with no build step.98++//! [`ASCII_ART`], [`LOGO_ANSI_RAW`], [`LOGO_SVG`], [`GL0W_SVG`],99++//! [`FAVICON_SVG`] and [`WORDMARK_SVG`] re-expose those static files for100++//! later issues (navbar #16, favicon #17, wiki README #19, agents page)101++//! with no build step.102+ //!103+ //! [`ascii_pre`] renders the banner as an escaped `<pre>` block (see104+ //! [`crate::layout::esc`]): the art itself is block glyphs plus spaces so105+@@ -43,6 +44,10 @@ pub const LOGO_ANSI_RAW: &str = include_str!("../static/logo-ansi.txt");106+ /// Header lockup, byte-for-byte `static/logo.svg` (mark + hu13 as <path>).107+ pub const LOGO_SVG: &str = include_str!("../static/logo.svg");108+ 109++/// gl0w mark, byte-for-byte `static/gl0w.svg` (from the gf1 brand source).110++/// Inlined into the header/footer so `currentColor` follows the site theme.111++pub const GL0W_SVG: &str = include_str!("../static/gl0w.svg");112++113+ #[allow(dead_code)]114+ /// Simplified 16px favicon variant, byte-for-byte `static/favicon.svg`115+ /// (mark only, no letters — documented choice for small-size legibility).116+diff --git a/static/gl0w.svg b/static/gl0w.svg117+new file mode 100644118+index 0000000..97b648c119+--- /dev/null120++++ b/static/gl0w.svg121+@@ -0,0 +1,4 @@122++<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 357 306" role="img" aria-label="gl0w functional laboratories — inverted triangle G">123++ <!-- traced from raster master: uniform 30u weight, sheared cuts, single gap upper-right -->124++ <path fill="currentColor" d="M2,2 L355,2 L320,62 L283,63 L304,29 L52,29 L179,250 L252,120 L138,120 L154,91 L303,91 L179,305 Z"/>125++</svg>126+diff --git a/static/style.css b/static/style.css127+index 471097d..33982a6 100644128+--- a/static/style.css129++++ b/static/style.css130+@@ -188,9 +188,9 @@ footer.site-footer .footer-provenance{margin:0;font-size:var(--fs-sm);text-align131+ .site-header .wrap.header-bar{display:flex;flex-wrap:nowrap;align-items:center;gap:.5rem .75rem}132+ .brand-lockup{display:inline-flex;align-items:center;gap:.5rem;flex:none;color:var(--fg);text-decoration:none;min-height:40px}133+ .brand-lockup:visited{color:var(--fg)}134+-.gl0w-mark{font:600 .8rem/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.18em;135+- text-transform:lowercase;color:var(--cyan);border:1px solid var(--border);padding:.35rem .45rem}136+-.brand-lockup:hover .gl0w-mark{color:var(--blue);border-color:var(--blue)}137++.gl0w-mark{display:inline-flex;align-items:center;color:var(--cyan);line-height:0;flex:none}138++.gl0w-mark svg{display:block;height:1.3rem;width:auto}139++.brand-lockup:hover .gl0w-mark,.footer-brand .gl0w-mark:hover{color:var(--blue)}140+ .lockup-slash{color:var(--border);font-weight:400}141+ .site-logo{display:block;width:auto;height:1.75rem;flex:none}142+ .hu13-word{font-weight:700;color:var(--blue)}143+diff --git a/tests/brand.rs b/tests/brand.rs144+index d81c023..77ceea2 100644145+--- a/tests/brand.rs146++++ b/tests/brand.rs147+@@ -58,8 +58,20 @@ fn header_and_footer_carry_gl0w_branding() {148+ for page in ["index.html", "agents.html", "issues/index.html"] {149+ let html = std::fs::read_to_string(out.join(page)).expect(page);150+ assert!(151+- html.contains("<span class=\"gl0w-mark\""),152+- "{page}: gl0w mark in header"153++ html.contains("<span class=\"gl0w-mark\" aria-hidden=\"true\"><svg"),154++ "{page}: gl0w logo mark in header"155++ );156++ assert!(157++ html.contains("viewBox=\"0 0 357 306\"") && html.contains("M2,2 L355,2"),158++ "{page}: gf1 gl0w mark geometry"159++ );160++ assert!(161++ !html.contains("<span class=\"gl0w-mark\" aria-hidden=\"true\">gl0w</span>"),162++ "{page}: text placeholder replaced by logo"163++ );164++ assert!(165++ html.contains("<a class=\"gl0w-mark\" href=\"https://gl0w.world\" rel=\"noopener\" aria-label=\"gl0w\">"),166++ "{page}: footer logo links gl0w.world"167+ );168+ assert!(169+ html.contains("hu13 — a gl0w project"),170+@@ -105,9 +117,19 @@ fn social_card_and_meta_present() {171+ 172+ #[test]173+ fn logo_has_no_baked_background() {174++ let out = build();175+ let logo =176+ std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("static/logo.svg"))177+ .unwrap();178++ let gl0w =179++ std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("static/gl0w.svg"))180++ .unwrap();181++ assert!(182++ gl0w.contains("viewBox=\"0 0 357 306\"") && gl0w.contains("fill=\"currentColor\""),183++ "vendored gf1 gl0w mark"184++ );185++ let built = std::fs::read_to_string(out.join("gl0w.svg")).unwrap();186++ assert_eq!(built, gl0w, "build emits the same gl0w logo");187+ assert!(!logo.contains("fill=\"#1a1b26\""), "no dark slab");188+ assert!(189+ logo.contains("@media (prefers-color-scheme:light)"),190+-- 191+2.56.0192+