Skip to content

Commit 430ffb0

Browse files
refactor(web): purge dead sections, share section metadata, polish UI
Delete 9 unused section components and ~1400 lines of dead CSS, hoist the section list to lib/sections.ts so the marginalia ribbon and the two progress rails share one source of truth, lazy-load the 144 KB filers JSON out of the layout chunk, restore neutral hardware-fit verdict copy, and add the missing mobile drawer + SVG theme-toggle.
1 parent 9710747 commit 430ffb0

42 files changed

Lines changed: 648 additions & 4183 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

web/app/globals.css

Lines changed: 371 additions & 1533 deletions
Large diffs are not rendered by default.

web/app/not-found.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Link from "next/link";
2+
import { Arrow } from "@/components/ui/arrow";
23

34
export default function NotFound() {
45
return (
@@ -53,9 +54,7 @@ export default function NotFound() {
5354
style={{ marginTop: 24 }}
5455
>
5556
Back to YuhoLens
56-
<span className="arr" aria-hidden="true">
57-
58-
</span>
57+
<Arrow className="arr" />
5958
</Link>
6059
</main>
6160
);

web/app/sitemap.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@ export const dynamic = "force-static";
44

55
const BASE = "https://yuholens.site";
66

7+
// Stable lastmod: derive from BUILD_DATE (set at build time via env), or
8+
// fall back to today. Avoids "always now" timestamps that misrepresent
9+
// content age to crawlers on every redeploy.
10+
function buildDate(): string {
11+
const env = process.env.NEXT_PUBLIC_BUILD_DATE;
12+
const d = env ? new Date(env) : new Date();
13+
return d.toISOString();
14+
}
15+
716
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
817
return [
918
{
1019
url: `${BASE}/`,
11-
lastModified: new Date(),
20+
lastModified: buildDate(),
1221
changeFrequency: "weekly",
1322
priority: 1,
1423
},

web/components/canvas/kanji-field.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export function KanjiField() {
181181
const obs = new IntersectionObserver(([e]) => {
182182
if (e.isIntersecting && !active) {
183183
active = true;
184-
raf = requestAnimationFrame(tick);
184+
if (!document.hidden) raf = requestAnimationFrame(tick);
185185
} else if (!e.isIntersecting && active) {
186186
active = false;
187187
cancelAnimationFrame(raf);
@@ -190,6 +190,23 @@ export function KanjiField() {
190190
obs.observe(canvas);
191191
raf = requestAnimationFrame(tick);
192192

193+
// Pause the rAF loop while the tab is hidden. The IntersectionObserver
194+
// above never fires "out" because the canvas is fixed (always
195+
// intersecting), so without this, particles keep advancing on a
196+
// backgrounded tab and burn CPU for no visible benefit.
197+
const onVisibility = () => {
198+
if (document.hidden) {
199+
if (active) {
200+
cancelAnimationFrame(raf);
201+
active = false;
202+
}
203+
} else if (!active) {
204+
active = true;
205+
raf = requestAnimationFrame(tick);
206+
}
207+
};
208+
document.addEventListener("visibilitychange", onVisibility);
209+
193210
const onMotionChange = (ev: MediaQueryListEvent) => {
194211
if (ev.matches) {
195212
active = false;
@@ -207,6 +224,7 @@ export function KanjiField() {
207224
ro.disconnect();
208225
cancelAnimationFrame(raf);
209226
window.removeEventListener("resize", resize);
227+
document.removeEventListener("visibilitychange", onVisibility);
210228
if (typeof motionMedia.removeEventListener === "function") {
211229
motionMedia.removeEventListener("change", onMotionChange);
212230
}

web/components/canvas/paper-rail.tsx

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,8 @@ type StageKey =
1212
| "problem"
1313
| "how"
1414
| "repro"
15-
| "demo"
1615
| "hardware"
17-
| "dag"
1816
| "readalong"
19-
| "kg2"
20-
| "reports"
21-
| "failures"
22-
| "manifest"
23-
| "faq"
2417
| "access";
2518

2619
type PaperSide = "right" | "left" | "centre";
@@ -79,15 +72,6 @@ const STAGES: Record<StageKey, StagePose> = {
7972
repro: { ...PARK_RIGHT, side: "right", texture: "rail", inkProgram: 3 },
8073
hardware: { ...PARK_RIGHT, side: "right", texture: "rail", inkProgram: 3 },
8174
access: { ...PARK_RIGHT, side: "right", texture: "footer", inkProgram: 5 },
82-
// Legacy stages — kept so type stays in sync with old data-paper-stage
83-
// attributes if they linger; all park on the right and are fade-hidden.
84-
demo: { ...PARK_RIGHT, side: "right", texture: "rail", inkProgram: 3 },
85-
dag: { ...PARK_RIGHT, side: "right", texture: "how", inkProgram: 2 },
86-
kg2: { ...PARK_RIGHT, side: "right", texture: "rail", inkProgram: 3 },
87-
reports: { ...PARK_RIGHT, side: "right", texture: "rail", inkProgram: 3 },
88-
failures: { ...PARK_RIGHT, side: "right", texture: "problem", inkProgram: 1 },
89-
manifest: { ...PARK_RIGHT, side: "right", texture: "manifest", inkProgram: 4 },
90-
faq: { ...PARK_RIGHT, side: "right", texture: "manifest", inkProgram: 4 },
9175
};
9276

9377
const cachedTextures: Partial<Record<TextureKey, THREE.Texture>> = {};

web/components/demo/__tests__/token-spring.test.tsx

Lines changed: 0 additions & 62 deletions
This file was deleted.

web/components/demo/decoder-toggle.tsx

Lines changed: 0 additions & 42 deletions
This file was deleted.

web/components/demo/demo-state-machine.ts

Lines changed: 0 additions & 91 deletions
This file was deleted.

0 commit comments

Comments
 (0)