Skip to content

feat(site): rebuild homepage as indigo scroll story#40

Open
drewstone wants to merge 2 commits into
masterfrom
feat/homepage-indigo-story
Open

feat(site): rebuild homepage as indigo scroll story#40
drewstone wants to merge 2 commits into
masterfrom
feat/homepage-indigo-story

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Rebuilds the homepage as a single-hue indigo scroll story.

What changed

  • Dispersion palette retired everywhere (hero text, knot shaders, trace lines, waterfall spans, chips, footer): single indigo luminance ramp #C7C9F5 → #818CF8 → #6366F1 → #4F46E5, neutrals, semantic red/green only.
  • New outline: WebGL knot hero (fresnel shader + bloom, poster fallback) → proof strip (real router numbers) → harness chapter (8 corrected marks, scroll-driven trace convergence) → Intelligence split-scroll: session-trace waterfall → analyst finding → ship-stage deal-out (cards land tilted, scrubbed by scroll; tunable via the CHOREO config at the top of the page script) → indigo product cards (new generated art) → open source section → pay-as-you-go pricing (copy sourced from live router site, links id.tangle.tools) → closing CTA.
  • Internal review surfaces (noindex, unlinked): /art-review, /ideas-review, /knot-lab.
  • Adds three; static fallbacks for reduced-motion, no-JS, and narrow viewports throughout.

Tuning openings

  • Deal-out feel: CHOREO + STAGE2_START in index.astro script (per-card timing, tilt, entry).
  • Stage pacing: .intel-flow height + .intel-step offsets.
  • Art: swap files in public/images/brand/{cards,picks}; briefs archived in gtm assets.

Screenshots in ~/company/gtm/execution-plans/assets/tangle-website-rebuild/ (home-v5-desktop/mobile, deal-mid/full).

drewstone added 2 commits July 2, 2026 06:55
Single-hue indigo system replaces the dispersion palette across every
surface. New homepage outline: WebGL knot hero with poster fallback,
proof strip from live router numbers, harness chapter with scroll-driven
trace convergence, Intelligence split-scroll (session-trace waterfall,
analyst finding, ship-stage deal-out with tunable CHOREO config),
indigo product-card art, open source section, pay-as-you-go pricing
sourced from live router copy, closing CTA, dispersion-free footer.

Internal review surfaces (noindex): /art-review, /ideas-review,
/knot-lab. Harness marks corrected (Claude Code spark, OpenCode
favicon, Hermes product mascot, designed Pi monogram). Adds three.js;
hero renders a fresnel-shader torus knot with bloom, static fallbacks
for reduced-motion, no-JS, and mobile.
…o-story

# Conflicts:
#	src/pages/blog/index.astro
#	src/pages/research.astro

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — c05933fb

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-02T10:58:49Z

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Value Audit — better-approach-exists

Verdict better-approach-exists
Concerns 5 (3 medium-concern, 2 weak-concern)
Heuristic 0.0s
Duplication 0.1s
Interrogation 260.9s (2 bridge agents)
Total 261.0s

💰 Value — better-approach-exists

Replaces the sparse homepage with a scroll-driven indigo narrative (WebGL hero, proof strip, harness rail, trace waterfall, deal-out ship cards, product cards, OSS, pricing); the core direction is sound, but it should reuse the existing StoryScroller component and shed dead CSS and internal-review p

  • What it does: Rebuilt src/pages/index.astro from a single hero-video page (~89 removed lines) into a 2,242-line scroll story: WebGL torus-knot hero with fresnel shader and bloom, proof strip, scroll-activated harness rail with SVG trace lines, pinned Intelligence section showing trace waterfall → analyst finding → deal-out ship cards, product cards, open-source section, pay-as-you-go pricing, and closing CTA. A
  • Goals it achieves: Makes the marketing homepage tell Tangle's product story end-to-end (sandbox → trace → intelligence → ship) with a single indigo brand system, real router numbers, and concrete proof points. Unifies visual language around one hue family and gives buyers a clear path from value prop to pricing to API key.
  • Assessment: Good on its merits for the homepage itself: coherent narrative, real data, accessible fallbacks (reduced motion, narrow viewport, static stack), and tighter messaging than the old single-hero page. The indigo-only palette and ship-stage choreography are intentional product-design choices, not code flaws.
  • Better / existing approach: The codebase already has src/components/ui/StoryScroller.astro, a pinned-scroll narrative component built for exactly the intelligence-stage pattern, yet the PR hand-rolls a duplicate inside index.astro. I also found ~375 lines of dead CSS in index.astro for an earlier iteration (classes .intel-head, .stage-nav, .sim-card, .analyst-card, .pr-card, etc. have no matching markup at src/pages/index.as
  • Model: opencode/kimi-for-coding/k2p7
  • Bridge attempts: 1

🎯 Usefulness — sound-with-nits

A coherent, well-integrated homepage rebuild that is the site's primary entry surface — everything is reachable as intended and the headline claims are backed by real data; only implementation-layer nits (dead CSS, an incomplete no-JS fallback) remain, which separate review passes own.

  • Integration: index.astro is the homepage at / — the most reachable surface in the site — wrapped in the existing BaseLayout and Header/Footer. /brand-kit (527 lines, complete) is linked from the new Footer company column (src/components/Footer.astro:31). /research was intentionally retired to a 301 redirect to a blog series (src/pages/research.astro:1-7), so old links resolve rather than 404 — not dead s
  • Fit with existing patterns: Fits the grain. This is a static Astro marketing site; the homepage was previously a simpler page, so this is a rebuild (not a parallel implementation competing with an established pattern). Adding three (^0.185.1) for a WebGL hero is the right tool and there is no pre-existing WebGL/animation pattern to duplicate or collide with — the old hero was static/video. The new indigo design tokens (`--
  • Real-world viability: Strong happy-path and degraded-motion coverage: the WebGL hero is gated behind !reduced && wide (index.astro:423) with a poster fallback, an IntersectionObserver pauses the render loop when offscreen (line 492), and reduced-motion/narrow screens get .static layouts for both the sandbox and intelligence chapters. The proof-strip headline is grounded: src/data/router-models.json reports `count:
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

💰 Value Audit

🟠 Scroll-driven Intelligence section reinvents existing StoryScroller [duplication] ``

src/components/ui/StoryScroller.astro already implements a pinned, scroll-driven, stage-switching narrative with sticky container, stage panels, and mobile fallback. The PR adds a parallel implementation in src/pages/index.astro:204-304 and :1081-1178 instead of composing with/extendeding that component. Better approach: use StoryScroller for the trace→analyze→ship narrative, or update StoryScroller if the new layout needs a different panel arrangement.

🟠 index.astro ships ~375 lines of dead CSS [maintenance] ``

src/pages/index.astro:1618-1993 contains CSS for classes (.intel-head, .stage-nav, .stage-area, .sim-card, .analyst-card, .pr-card, .pr-diff, etc.) that do not appear in the page markup or script. These are leftovers from an earlier iteration of the intelligence section and will confuse future edits. Better approach: delete this block before merge.

🟠 Internal review pages and assets bloat the production build [proportion] ``

The PR adds /art-review, /ideas-review, and /knot-lab (src/pages/art-review.astro:1, src/pages/ideas-review.astro:1, src/pages/knot-lab.astro:1) plus src/data/art-review.json, src/data/briefs-v2.mjs, src/data/briefs-v3.mjs, src/data/router-models.json, and public/images/art-review (~2.2 MB). These are explicitly unlinked/noindex review surfaces but still ship in every deploy. Better approach: keep review artifacts in ~/company/gtm or a non-production branch; do not bundle them into the public si

🟡 Unused 3.1 MB hero-loop.mp4 is added [proportion] ``

public/videos/hero-loop.mp4 is included in the commit but not referenced anywhere in the new homepage or other pages (grep for hero-loop returns no Astro/HTML/CSS/JS hits). The WebGL hero uses /images/brand/knot-poster.webp as its fallback. Better approach: remove the unused video.

🟡 New homepage mostly ignores canonical ui/ primitives [against-grain] ``

The codebase has src/components/ui/Section.astro, CtaBlock.astro, FeatureCard.astro, BentoCell.astro, and Card.astro to replace hand-rolled sections, yet index.astro defines its own .shell layout, buttons, product cards, pricing steps, and footer-style CTA. Some of this is justified by the bespoke scroll behavior, but it creates more one-off styles to maintain. Better approach: where the layout is standard (proof strip, product cards, pricing, closing CTA), compose from the existing primitives.


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260702T113231Z

@tangletools

Copy link
Copy Markdown
Contributor

⚠️ Review Interrupted — c05933fb

The review runner stopped before publishing a final verdict: max_run_seconds.

State Detail
Interrupted max run seconds

No review verdict was produced for this run. Trigger a fresh review on the current PR head if the PR is still open.

tangletools · #40 · model: kimi-for-coding · updated 2026-07-02T13:27:50Z

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — c05933fb

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-02T13:47:17Z

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Value Audit — better-approach-exists

Verdict better-approach-exists
Concerns 5 (1 strong-concern, 2 medium-concern, 2 weak-concern)
Heuristic 0.0s
Duplication 0.1s
Interrogation 276.6s (2 bridge agents)
Total 276.7s

💰 Value — better-approach-exists

A coherent visual and narrative overhaul of the homepage that is implemented as a 2,242-line monolithic Astro file full of dead CSS, ignoring the repo's own extracted component primitives and duplicating WebGL code.

  • What it does: Rebuilds the Tangle homepage as a single-hue indigo scroll story: a WebGL torus-knot hero (Three.js fresnel shader + bloom, with poster/reduced-motion/no-JS fallbacks), a proof strip, a scroll-driven sandbox harness chapter, an Intelligence split-scroll story (trace waterfall → analyst finding → deal-out ship-stage), product cards, open-source section, pay-as-you-go pricing, and a rewritten footer
  • Goals it achieves: Unify the site under one indigo material palette; replace the previous sparse hero with a concrete product story that shows sandbox → trace → analysis → ship; surface real proof points (477+ models, 8 harnesses); and guide visitors to the console, docs, and API key signup. It also retires warm paper, lowers display weights to 600, and documents the new brand system in /brand-kit.
  • Assessment: The direction is good: the story maps to the actual product loop, the numbers are sourced from live router data, and the indigo system is a real improvement over the previous dispersed palette. But the implementation is unnecessarily monolithic. The homepage file grew from 188 lines to 2,242 lines (src/pages/index.astro:1), mixing markup, ~200 lines of inline Three.js, and ~1,600 lines of inline C
  • Better / existing approach: The right architecture is to compose the page from existing and new components instead of inlining everything. Existing primitives should be reused or extended: Section.astro for page sections, Hero.astro or a new KnotHero component for the WebGL hero, Button.astro for CTAs, StatsStrip.astro for the proof strip, FeatureCard.astro/Card.astro for product cards, and CtaBlock.astro for the closing CTA
  • Model: opencode/kimi-for-coding/k2p7
  • Bridge attempts: 1

🎯 Usefulness — sound-with-nits

A coherent, well-grounded rebuild of the homepage as a single-hue scroll story that wires in cleanly, ships correct fallbacks, and leaves intentional internal-review surfaces — no dead or competing surface.

  • Integration: Fully reachable. The homepage is the root route, linked from Header.astro:11; /brand-kit is linked from Footer.astro:16. The three review pages (art-review, ideas-review, knot-lab) are deliberately unlinked + noindex with stated internal purpose (art ranking, interaction prototypes, WebGL knot lab) and each consumes its data: art-review.astro:4-6 reads art-review.json + briefs-v2/v3.mjs; ideas-rev
  • Fit with existing patterns: Fits the grain. Replaces a thin 188-line master homepage with a richer version using the existing BaseLayout, CSS vars (--font-mono/--font-display), and the established .reveal IntersectionObserver pattern. Adds three as a dependency — appropriate and the only sane way to get the WebGL knot; poster + reduced-motion + narrow-viewport fallbacks mean the dependency degrades cleanly rather than bl
  • Real-world viability: Robust on the realistic paths that matter for a marketing page. Hero WebGL only initializes when !reduced && wide (index.astro:423), else falls back to static poster and a static-hero class; rendering pauses when the canvas leaves the viewport (IntersectionObserver, :492); sizing via ResizeObserver (:484). Both scroll choreographies rAF-throttle passive scroll listeners and short-circuit to a `.
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

🎯 Usefulness Audit

🟡 Homepage hardcodes the proof numbers instead of reading the snapshot it ships [robustness] ``

index.astro:145-146 hardcodes '477+' and '61+' providers, and :86 hardcodes '477+'. The PR adds src/data/router-models.json (count:477, fetched 2026-07-01) but the homepage never imports it — only ideas-review.astro:5 does. The headline proof will silently drift from the data file the day a model is added, and '61+ providers' has no backing field in the JSON at all (it only carries ids). Minor available improvement: derive the model count from the JSON (and snapshot a provider count) so the proo

💰 Value Audit

🔴 Homepage is a 2,242-line monolith that ignores existing UI primitives [against-grain] ``

src/pages/index.astro grew from 188 lines to 2,242 lines, with all markup, ~200 lines of Three.js, and ~1,600 lines of CSS inline. The repo has already extracted Section.astro (replacing hand-rolled wf-section patterns 36×), Hero.astro (replacing 8 bespoke hero blocks), CtaBlock.astro, Button.astro, StatsStrip.astro, FeatureCard.astro, and Card.astro. The new homepage defines its own buttons (.btn, .btn-primary), sections, hero, stats/proof strip, product cards, and CTA instead of reusing or ext

🟠 WebGL knot shader is duplicated between homepage and knot-lab [duplication] ``

The fresnel dispersion shader, bloom setup, and render loop appear nearly identically in src/pages/index.astro:411-510 and src/pages/knot-lab.astro:26-172. The better approach is a shared KnotHero.astro component that accepts props (camera offset, drag-or-parallax behavior, reduced-motion handling) and is reused by both pages.

🟠 Dead CSS for abandoned stage variants remains in the file [maintenance] ``

The CSS block at src/pages/index.astro:1664-1993 defines .stage-nav, .sim-card, .analyst-card, .pr-card, and related rules, but grep finds no matching HTML class attributes in the file. These appear to be leftovers from earlier iterations of the Intelligence story. Dead rules in a 2,242-line file make the page harder to maintain and review.

🟡 Internal review pages add ~835 lines of unlinked/noindex code [proportion] ``

src/pages/art-review.astro, ideas-review.astro, and knot-lab.astro are noindex and unlinked, but ideas-review.astro alone is 470 lines of live prototypes. They are useful for tuning, but their scope could be trimmed—especially ideas-review, whose non-shipped experiments could live in gtm assets rather than in the deployable site.


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260702T135300Z

@tangletools

Copy link
Copy Markdown
Contributor

✅ No Blockers — c05933fb

Review health 100/100 · Reviewer score 31/100 · Confidence 95/100 · 26 findings (4 medium, 22 low)

opencode-kimi glm aggregate
Readiness 53 31 31
Confidence 95 95 95
Correctness 53 31 31
Security 53 31 31
Testing 53 31 31
Architecture 53 31 31

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 8/8 planned shots over 85 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 85 changed files. Global verifier still owns final merge decision.

🟠 MEDIUM Mobile CTA label inconsistent with desktop — src/components/Header.astro

The desktop CTA was updated to 'Open console' (line 22) but the mobile menu still shows 'Launch Agent' (line 40). Same href, same component, different labels will confuse mobile users and looks unfinished.

🟠 MEDIUM router-models.json breaks deprecated-model CI check — src/data/router-models.json

pnpm check:models treats .json under src/ as invocation config and scans src/data/router-models.json. The file is a display catalog (used by ideas-review.astro idea #8), but the scanner flags numerous IDs as deprecated (e.g. gpt-5-codex, o3-mini, gemini-3.5-flash) and exits 1. Reproduced locally: the output lists src/data/router-models.json findings and the script fails. Fix: add src/data/router-models.json to .deprecated-models.allow.json files array, or adjust scripts/check-models.mjs to skip src/data/*.json catalog files.

🟠 MEDIUM index.astro contains extensive dead and duplicated CSS — src/pages/index.astro

The stylesheet contains large duplicated blocks (products/sandbox/intelligence CSS appears twice at lines ~830 and ~1360) and entire dead sections for an earlier markup iteration: .stage-nav, .stage-area, .stage-0/1/2 (lines ~1612+), .sim-card/.trace-list/.analyst-card (lines ~1745+), and .pr-card/.pr-actions (lines ~1839+). None of these selectors match the current HTML, which uses .istage/.istage-0/1/2 and .wf-card/.ann-card instead. This is not a runtime bug, but it materially bloats the file (style block is ~1630 lines in a 2243-line file), makes future edits error-prone, and indicates cleanup was not finished. Fix: delete the unused .stage-*, .sim-card/.trace-list/.analyst-card, and .pr-card blocks; consolidate the duplicate products/sandbox/intelligence blocks into single definitions

🟠 MEDIUM index.astro ships ~650 lines of duplicate + orphaned CSS, with a conflicting .intel-flow height — src/pages/index.astro

The <style> block defines the same section selectors twice. .products-section appears at line 830 and again verbatim at line 1360; same for .statement, .statement-grad, .product-cards, .p-card/.p-card-art/.p-card-body, .sb-section, .sb-flow, .sb-tile, and .intel-section/.intel-flow/.intel-sticky. The second block (lines ~1357-2010) is a mix of (a) exact duplicates of the first and (b) fully orphaned selectors whose classes NEVER appear in the markup: .stage-nav, .stage/.stage-0/1/2, .stage-area, .sim-card, `

🟡 LOW Five SVGs missing trailing newline (No newline at end of file) — public/images/harness/claude-code.svg

git diff reports '\ No newline at end of file' for claude-code.svg, opencode.svg, github.svg, linear.svg, slack.svg (pi.svg is fine). Purely cosmetic; some linters/CI formatters flag it. Add a single \n at EOF to match pi.svg and the repo's other text assets.

🟡 LOW opencode.svg carries a no-op prefers-color-scheme style block — public/images/harness/opencode.svg

The trailing <style> sets filter: none in BOTH light and dark media-query branches — i.e. it never changes anything. Either remove the block or give it a real purpose (e.g. invert/dim for dark mode). Harmless but dead CSS inside a shipped asset.

🟡 LOW Two product images added but referenced nowhere in src/ — public/images/product/sandbox-full.webp

sandbox-full.webp (137472 B, 2556x1758) and sandbox-workspace.webp (62474 B, 1404x934) are committed but grep across src/ (.astro/.mdx/.md/.ts/.tsx/.json) returns zero references; the full-PR diff to src/pages/index.astro does not mention either path. Net ~200KB of unreferenced bundle weight today. Either wire them into the sandbox product section or drop them until the consuming component lands. Not blocking — files are valid and inert.

🟡 LOW Unused product screenshots and inconsistent directory naming — public/images/product/sandbox-full.webp

sandbox-full.webp and public/images/product/sandbox-workspace.webp are added but no source file references them (grep for 'sandbox-full', 'sandbox-workspace', and 'images/product' in src/ returns nothing). They are also under public/images/product/ (singular), whereas existing product screenshots are under public/images/products/ (plural). Either wire them into the intended page/CSS or remove them to avoid dead weight.

🟡 LOW Product 'hue' field is uniform, undermining the per-product hue intent — src/components/Footer.astro

All three products share hue: '#818CF8' (Sandbox, Intelligence, Inference), so style={color: ${p.hue}} renders identically for every product. The component is wired to support per-product color but the data doesn't deliver it. Impact: visual only; the dispersion/hairline gradient is unaffected. Fix: either assign distinct hues per product or drop the hue field and hard-code the single color to remove dead configurability.

🟡 LOW Redundant/conflicting border declarations on .ft-console — src/components/Footer.astro

The rule sets border-bottom: 1px solid transparent; then border-image: linear-gradient(...) 1; then re-asserts border-bottom-width: 1px; border-bottom-style: solid;. When border-image is set it paints over the declared border-color/width/style, so the transparent + width/style re-assertions are dead. Cosmetic only, no functional impact. Fix: keep just border-bottom: 1px solid; border-image: linear-gradient(90deg, #A5AAFC, #6366F1, #4F46E5) 1; and drop the redundant lines.

🟡 LOW Home link falsely claims current page everywhere — src/components/Header.astro

<a href='/' aria-current='page' ...> is hardcoded, so screen readers will announce the home link as the current page on every route. Pre-existing but in the shot file; should be conditional on Astro.url.pathname === '/'.

🟡 LOW Mobile menu CTA text diverges from desktop after rename — src/components/Header.astro

The diff renamed the desktop CTA from 'Launch Agent' to 'Open console' at line 22 but left the duplicate mobile-menu CTA at line 40 as 'Launch Agent'. grep confirms these are the only two occurrences in src/ and they now disagree. Impact: inconsistent label for the same destination (https://ai.tangle.tools) between desktop and mobile breakpoints, and the renamed wording never reaches mobile users. Fix: update Header.astro:40 to read 'Open console' to match [line 22](https://github.com/tangle-network/tangle-website/blob/c05933fba561844

🟡 LOW VIDEO_MOTION exported but never imported — src/data/briefs-v2.mjs

grep finds VIDEO_MOTION only at its definition; art-review.astro imports BRAND_CORE, HERO_FIELD_V2, CARD_SANDBOX, CARD_INTELLIGENCE, CARD_INFERENCE from v2 — VIDEO_MOTION is dead. Not a bug (exports are a public surface), but either wire it into the gallery or drop it to keep the module honest. Impact: none at runtime.

🟡 LOW Denormalized count field can silently drift from ids.length — src/data/router-models.json

"count": 477 is hand-maintained alongside the 477-entry ids array. Today they agree (verified: ids.length===477). If a future edit appends/removes an ID without updating count, consumers trusting count (e.g. ideas-review.astro copy '477-model snapshot') will lie. Fix: derive the displayed number from ids.length at the call site, or assert count===ids.length in the consumer, rather than storing both.

🟡 LOW No trailing newline — src/data/router-models.json

File ends with ] and no newline (diff shows '\ No newline at end of file'). POSIX/repo-lint convention prefers a final newline; some formatters/prettier configs flag it. Trivial fix, no runtime impact on JSON.parse.

🟡 LOW Snapshot labeled 'live' in consumer but is a hardcoded static fetch — src/data/router-models.json

"fetched": "2026-07-01" pins this to a single day; ideas-review.astro idea #8 copy says 'IDs are from the live catalog snapshot' and 'real model IDs from the live catalog'. The data is a stale-by-construction snapshot that will drift from the real router. Acceptable for an internal noindex prototype page, but the word 'live' overstates it — consider 'snapshot dated 2026-07-01' in the page copy so the gallery doesn't mislead during a future review.

🟡 LOW Duplicate @media (max-width: 640px) blocks in BlogLayout — src/layouts/BlogLayout.astro

The new table-scroll media query (lines 418-432) and the pre-existing hero/article media query (lines 445-484) share the same max-width: 640px breakpoint. Functionally correct (both apply), but they could be merged into one block for maintainability. Pure style nit — no behavioral impact.

🟡 LOW Homepage hero WebGLRenderer creation is unguarded; a context-creation throw leaves a blank hero with no poster fallback — src/pages/index.astro

new THREE.WebGLRenderer({ canvas: knotCanvas, antialias: true }) (line 426) throws when WebGL is unavailable/blocked (some corporate proxies, locked-down browsers, headless crawlers with no GPU). The static-hero fallback (document.documentElement.classList.add('static-hero') at line 511) only runs in the else branch of if (knotCanvas && !reduced && wide) — it is NOT reached when the renderer throws. Result: on WebGL failure the <canvas> stays at opacity:0 (its default) AND .hero-poster stays display:none, so the hero shows only

🟡 LOW knot-lab.astro rAF loop never pauses when the page is off-screen or backgrounded — src/pages/knot-lab.astro

const frame = () => { ... composer.render(); requestAnimationFrame(frame); } runs unconditionally with no visibility gate. The homepage hero correctly uses an IntersectionObserver to skip composer.render() when !visible (index.astro line 499), but knot-lab.astro omits this. Impact: continuous GPU/composer work while the tab is backgrounded or scrolled away. Internal noindex page so impact is limited, but it is an avoidable battery/CPU drain. Fix: add the same IntersectionObserver-on-canvas visibility gate used in the homepage.

🟡 LOW research.astro 301 is emitted as a meta-refresh, not a real 301, in static output mode — src/pages/research.astro

return Astro.redirect('/blog/series/the-self-improving-stack', 301) runs under output: 'static' (astro.config.mjs:12). In static mode Astro ignores the status code and generates an HTML redirect page with <meta http-equiv="refresh"> plus a canonical link, which search engines treat as a soft redirect (not a true 301). Functionally correct for users and the target resolves (verified), but if a hard 301 matters for SEO link equity, configure redirects in astro.config.mjs (supported for static adapters) or move the redirect to the host/edge. Acceptable as-is for a dormant route; flagging only because the literal 301 in source is not what ships.

🟡 LOW --depth-0 and --depth-5 are defined but never consumed — src/styles/global.css

git grep for 'var(--depth-0)' and 'var(--depth-5)' across the entire repo (css + astro + ts) returns ZERO matches. These two new tokens are dead weight — either wire them into the surfaces the comments describe ('wells, page edges, behind hero art' / 'active/pressed, highest lift') or drop them until a consumer exists. Impact: premature abstraction, future readers will assume the ladder is in use. Fix: remove the two lines, or migrate at least one call site (e.g. html/body background-color: var(--depth-1) → var(--depth-0)) in this same PR.

🟡 LOW --font-display fallback chain weaker than --font-sans — src/styles/global.css

--font-display is now '"Inter", sans-serif' while --font-sans keeps '"Inter", "DM Sans", ui-sans-serif, system-ui, sans-serif'. If Inter's @font-face fails to load, headings drop straight to generic sans-serif while body text renders system-ui — inconsistent fallback behavior between the two stacks. Minor brand robustness nit; fix by mirroring the system-ui fallback: '--font-display: "Inter", ui-sans-serif, system-ui, sans-serif;'.

🟡 LOW .wf-h1 line-height source-of-truth split between hardcoded and token — src/styles/global.css

Base .wf-h1 sets 'line-height: 0.95;' (hardcoded literal, changed from 0.9) while the media-query override at line 3322 uses 'line-height: var(--type-h1-line) !important;' (= 1.02). The two values come from different sources and the jump (0.95 → 1.02 at the breakpoint) is larger than the h1 token itself prescribes (1.02). Either set the base to var(--type-h1-line) too, or document why the large-screen override relaxes leading. Pre-existing pattern of hardcoded-vs-token split, but this PR widens it by converting sibling props (weight, tracking) to tokens while leaving line-height literal.

🟡 LOW Comment overstates ladder completeness; --depth-1..4 still undefined — src/styles/global.css

The header comment reads 'Full contrast-checked ladder' and the file references --depth-1 (lines 352, 360, 2287), --depth-2 (2428, 2482, 2877), --depth-3 (2340, 2530, 2582, 2849, 2927, 2940, 2997, 3074, 3285), --depth-4 (2347, 2541, 2591, 2934, 3298, 3481) — none of which are defined in this file, fonts.css, or any tailwind/astro config at HEAD. This is pre-existing (base commit has the same gap), so NOT a regression introduced here, but the new 'full ladder' comment is misleading about what this PR delivers. Fix: either define the missing rungs as part of the indigo ladder, or reword the comment to 'adds the two missing poles (--depth-0/--depth-5); mid-rungs --depth

🟡 LOW Duplicate root declarations shadow earlier token values — src/styles/global.css

Within the same :root block --editorial-paper is first set to #f4f4f9 at line 226 and then overwritten to var(--paper-0) at line 250; --editorial-nav-bg is first set to rgba(12, 11, 29, 0.88) at line 230 and overwritten to rgba(17, 18, 45, 0.88) at line 252. Because both declarations t

🟡 LOW Updated .wf-h1/.wf-h3 rules are overridden by later !important reset — src/styles/global.css

The diff updates .wf-h1 (line ~2192) and .wf-h3 (line ~2203) to use the new type tokens, but both are later overridden by the foundation reset at lines 3319 and 3350, which applies !important to font-size, font-weight, letter-spacing, and line-height. The weight/tracking still align because the reset consumes the same CSS variables, but the font-size and line-height values in the earlier blocks are dead code, so edits there are no-ops. Either remove the redundant earlier overrides or consolidate the display scale in one place.


tangletools · 2026-07-02T14:19:31Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 26 non-blocking findings — c05933fb

Full multi-shot audit completed 8/8 planned shots over 85 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 8/8 planned shots over 85 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-02T14:19:31Z · immutable trace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants