feat(site): rebuild homepage as indigo scroll story#40
Conversation
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
left a comment
There was a problem hiding this comment.
✅ 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
left a comment
There was a problem hiding this comment.
🟠 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)./researchwas 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.staticlayouts 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.
|
| 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
left a comment
There was a problem hiding this comment.
✅ 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
left a comment
There was a problem hiding this comment.
🟠 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
.revealIntersectionObserver pattern. Addsthreeas 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-heroclass; 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.
✅ No Blockers —
|
| 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-sectionappears 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: nonein 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;thenborder-image: linear-gradient(...) 1;then re-assertsborder-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 justborder-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 onAstro.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: 640pxbreakpoint. 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 theelsebranch ofif (knotCanvas && !reduced && wide)— it is NOT reached when the renderer throws. Result: on WebGL failure the<canvas>stays atopacity:0(its default) AND.hero-posterstaysdisplay: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 skipcomposer.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 underoutput: '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, configureredirectsin 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 literal301in 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
:rootblock--editorial-paperis first set to#f4f4f9at line 226 and then overwritten tovar(--paper-0)at line 250;--editorial-nav-bgis first set torgba(12, 11, 29, 0.88)at line 230 and overwritten torgba(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!importanttofont-size,font-weight,letter-spacing, andline-height. The weight/tracking still align because the reset consumes the same CSS variables, but thefont-sizeandline-heightvalues 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
left a comment
There was a problem hiding this comment.
✅ 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
Rebuilds the homepage as a single-hue indigo scroll story.
What changed
#C7C9F5 → #818CF8 → #6366F1 → #4F46E5, neutrals, semantic red/green only.CHOREOconfig 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./art-review,/ideas-review,/knot-lab.three; static fallbacks for reduced-motion, no-JS, and narrow viewports throughout.Tuning openings
CHOREO+STAGE2_STARTinindex.astroscript (per-card timing, tilt, entry)..intel-flowheight +.intel-stepoffsets.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).