diff --git a/web/public/video/pipelinescore-product-720.mp4 b/web/public/video/pipelinescore-product-720.mp4
new file mode 100644
index 0000000..81565c6
Binary files /dev/null and b/web/public/video/pipelinescore-product-720.mp4 differ
diff --git a/web/public/video/pipelinescore-product-poster.jpg b/web/public/video/pipelinescore-product-poster.jpg
new file mode 100644
index 0000000..a71f836
Binary files /dev/null and b/web/public/video/pipelinescore-product-poster.jpg differ
diff --git a/web/public/video/pipelinescore-product.mp4 b/web/public/video/pipelinescore-product.mp4
new file mode 100644
index 0000000..aa16e5c
Binary files /dev/null and b/web/public/video/pipelinescore-product.mp4 differ
diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx
index e7b5489..2bb1442 100644
--- a/web/src/app/page.tsx
+++ b/web/src/app/page.tsx
@@ -3,6 +3,7 @@ import { DataUnavailable } from "@/components/DataUnavailable";
import { getHardwareBoard, getLeaderboardModels, getStats } from "@/lib/api";
import { BenchTable } from "@/components/BenchTable";
import { CopyCommand } from "@/components/CopyCommand";
+import { ProductFilm } from "@/components/ProductFilm";
import { CATEGORY_LABELS, CATEGORY_WEIGHTS, TIERS } from "@/lib/tiers";
import { modelMatchups, rigMatchups } from "@/lib/matchups";
@@ -28,7 +29,8 @@ export default async function Home() {
{/* Masthead — data-first, no hero. The board is the homepage. */}
-
+
+
LLM benchmarks · v3 testpack · deterministic · no API key
@@ -74,6 +76,8 @@ export default async function Home() {
See where you'd rank →
+
+
{/* Instrument strip */}
diff --git a/web/src/components/ProductFilm.tsx b/web/src/components/ProductFilm.tsx
new file mode 100644
index 0000000..4f06ba7
--- /dev/null
+++ b/web/src/components/ProductFilm.tsx
@@ -0,0 +1,56 @@
+"use client";
+
+import { useEffect, useRef, useState } from "react";
+
+/**
+ * The 20-second product video, muted and looping. It plays only while on screen,
+ * and not at all for people who ask for reduced motion: they get the poster and
+ * the player controls instead.
+ */
+export function ProductFilm() {
+ const ref = useRef(null);
+ const [reduced, setReduced] = useState(false);
+
+ useEffect(() => {
+ const video = ref.current;
+ if (!video) return;
+ const motion = window.matchMedia("(prefers-reduced-motion: reduce)");
+ let visible = false;
+ const sync = () => {
+ setReduced(motion.matches);
+ if (visible && !motion.matches && !document.hidden) video.play().catch(() => {});
+ else video.pause();
+ };
+ const observer = new IntersectionObserver(([entry]) => {
+ visible = entry.isIntersecting;
+ sync();
+ }, { threshold: 0.25 });
+ observer.observe(video);
+ motion.addEventListener("change", sync);
+ document.addEventListener("visibilitychange", sync);
+ return () => {
+ observer.disconnect();
+ motion.removeEventListener("change", sync);
+ document.removeEventListener("visibilitychange", sync);
+ };
+ }, []);
+
+ return (
+
+
+
+ );
+}