diff --git a/web/components/hq/resources-showcase.tsx b/web/components/hq/resources-showcase.tsx
index ab6604b..b16f42f 100644
--- a/web/components/hq/resources-showcase.tsx
+++ b/web/components/hq/resources-showcase.tsx
@@ -1,7 +1,7 @@
"use client";
import Link from "next/link";
-import { useEffect, useState } from "react";
+import { useEffect, useRef, useState } from "react";
import { useReducedMotion } from "framer-motion";
/* The resources feature, rebuilt as a horizontal "expanding panels" accordion
@@ -18,6 +18,12 @@ type Service = {
label: string;
href: string;
icon: React.ReactNode;
+ /** Card artwork (#220). Re-encoded to 600px wide, CRF 30, audio stripped,
+ +faststart — 3.4MB of source became 1.3MB across all four. */
+ video: string;
+ /** First frame. This is all that loads until a panel is opened, and all a
+ reduced-motion visitor ever sees. */
+ poster: string;
};
const SERVICES: Service[] = [
@@ -28,6 +34,8 @@ const SERVICES: Service[] = [
label: "basics",
href: "/resources#getting-started",
icon: ,
+ video: "/resource-getting-started.mp4",
+ poster: "/resource-getting-started-poster.jpg",
},
{
n: "02",
@@ -36,6 +44,8 @@ const SERVICES: Service[] = [
label: "crew",
href: "/resources#finding-people",
icon: ,
+ video: "/resource-finding-people.mp4",
+ poster: "/resource-finding-people-poster.jpg",
},
{
n: "03",
@@ -44,6 +54,8 @@ const SERVICES: Service[] = [
label: "season",
href: "/resources#leveling-up",
icon: ,
+ video: "/resource-leveling-up.mp4",
+ poster: "/resource-leveling-up-poster.jpg",
},
{
n: "04",
@@ -52,6 +64,8 @@ const SERVICES: Service[] = [
label: "toolkit",
href: "/resources#tools",
icon: ,
+ video: "/resource-tools.mp4",
+ poster: "/resource-tools-poster.jpg",
},
];
@@ -149,11 +163,7 @@ function ServicePanel({
{s.desc}
-
+
{/* bottom label */}
@@ -169,6 +179,48 @@ function ServicePanel({
);
}
+/* ---- Card artwork (#220) ----
+
+ Only the open panel plays. `preload="none"` means nothing but the poster is
+ fetched until a panel is actually opened, so the four clips cost 0 bytes on
+ first paint and at most one of them ever decodes at a time. Under
+ prefers-reduced-motion the video is never started, leaving the poster — which
+ is why every clip needs one that reads on its own.
+
+ Decorative, so aria-hidden and no alt: the panel is already a labelled link
+ ("Open {title} resources") above a visible heading and description, and
+ narrating "VHS titling reading BUILD" would add noise, not information. */
+function PanelMedia({ s, active }: { s: Service; active: boolean }) {
+ const reduceMotion = useReducedMotion();
+ const videoRef = useRef(null);
+
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video) return;
+ if (active && !reduceMotion) {
+ video.play().catch(() => {});
+ return;
+ }
+ video.pause();
+ }, [active, reduceMotion]);
+
+ return (
+
+
+
+ );
+}
+
/* ---- Mobile stacked card ---- */
function MobileServiceCard({ s }: { s: Service }) {
@@ -187,6 +239,21 @@ function MobileServiceCard({ s }: { s: Service }) {
{s.title}
{s.desc}
+ {/* The still, not the clip. Four autoplaying videos stacked down a phone
+ would burn data and battery for decoration, and only one can be on
+ screen at a time anyway. Lazy so it costs nothing until scrolled to.
+ Decorative — the card is a link with a visible heading. */}
+
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+

+
{s.icon}
{s.label}
diff --git a/web/public/resource-finding-people-poster.jpg b/web/public/resource-finding-people-poster.jpg
new file mode 100644
index 0000000..14442cf
Binary files /dev/null and b/web/public/resource-finding-people-poster.jpg differ
diff --git a/web/public/resource-finding-people.mp4 b/web/public/resource-finding-people.mp4
new file mode 100644
index 0000000..b8ce55d
Binary files /dev/null and b/web/public/resource-finding-people.mp4 differ
diff --git a/web/public/resource-getting-started-poster.jpg b/web/public/resource-getting-started-poster.jpg
new file mode 100644
index 0000000..8c17491
Binary files /dev/null and b/web/public/resource-getting-started-poster.jpg differ
diff --git a/web/public/resource-getting-started.mp4 b/web/public/resource-getting-started.mp4
new file mode 100644
index 0000000..6109634
Binary files /dev/null and b/web/public/resource-getting-started.mp4 differ
diff --git a/web/public/resource-leveling-up-poster.jpg b/web/public/resource-leveling-up-poster.jpg
new file mode 100644
index 0000000..f4be2ed
Binary files /dev/null and b/web/public/resource-leveling-up-poster.jpg differ
diff --git a/web/public/resource-leveling-up.mp4 b/web/public/resource-leveling-up.mp4
new file mode 100644
index 0000000..1f22e53
Binary files /dev/null and b/web/public/resource-leveling-up.mp4 differ
diff --git a/web/public/resource-tools-poster.jpg b/web/public/resource-tools-poster.jpg
new file mode 100644
index 0000000..7acd508
Binary files /dev/null and b/web/public/resource-tools-poster.jpg differ
diff --git a/web/public/resource-tools.mp4 b/web/public/resource-tools.mp4
new file mode 100644
index 0000000..1699591
Binary files /dev/null and b/web/public/resource-tools.mp4 differ