fix(ui): replace FauxFrame SVG scenes with clean dark placeholder; strip fake LiveStrip animation: visuals.jsx

This commit is contained in:
Zac Gaetano 2026-05-22 09:31:57 -04:00
parent f58fe95f0d
commit 6ad277275b

View file

@ -1,7 +1,5 @@
// visuals.jsx - reusable visual elements: thumbnails, waveforms, sparklines, filmstrips
const { thumbGrad } = window.ZAMPP_DATA;
function AssetThumb({ asset, size = "md" }) {
const aspect = size === "tall" ? "9 / 16" : "16 / 9";
const seed = asset.seed || 1;
@ -18,104 +16,20 @@ function AssetThumb({ asset, size = "md" }) {
}
return (
<div className="asset-thumb" style={{ background: thumbGrad(seed), aspectRatio: aspect }}>
<div className="asset-thumb" style={{ background: "var(--bg-2)", aspectRatio: aspect }}>
<FauxFrame seed={seed} />
<div className="scanlines" />
</div>
);
}
function FauxFrame({ seed }) {
const shots = ["stage", "track", "interview", "aerial", "crowd", "trophy"];
const shot = shots[seed % shots.length];
return (
<svg viewBox="0 0 160 90" preserveAspectRatio="xMidYMid slice" className="thumb-svg">
<defs>
<linearGradient id={`sky-${seed}`} x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stopColor="hsl(220 30% 18%)" />
<stop offset="1" stopColor="hsl(280 25% 8%)" />
</linearGradient>
<linearGradient id={`ground-${seed}`} x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stopColor="hsl(220 15% 12%)" />
<stop offset="1" stopColor="hsl(220 15% 6%)" />
</linearGradient>
</defs>
{shot === "stage" && (
<>
<rect width="160" height="55" fill={`url(#sky-${seed})`} />
<rect y="55" width="160" height="35" fill={`url(#ground-${seed})`} />
<circle cx="50" cy="30" r="14" fill="hsl(40 60% 50% / 0.6)" />
<rect x="20" y="45" width="120" height="20" fill="hsl(220 30% 8% / 0.6)" />
<rect x="40" y="55" width="6" height="20" fill="hsl(220 20% 40%)" />
<rect x="55" y="50" width="6" height="25" fill="hsl(220 20% 40%)" />
<rect x="100" y="52" width="6" height="23" fill="hsl(220 20% 40%)" />
<rect x="115" y="58" width="6" height="17" fill="hsl(220 20% 40%)" />
</>
)}
{shot === "track" && (
<>
<rect width="160" height="50" fill={`url(#sky-${seed})`} />
<rect y="50" width="160" height="40" fill="hsl(20 15% 12%)" />
<path d="M0 60 L160 50 L160 90 L0 80 Z" fill="hsl(20 25% 18%)" />
<path d="M0 70 L160 60" stroke="hsl(40 80% 60% / 0.5)" strokeWidth="0.5" strokeDasharray="4 2" />
<rect x="60" y="48" width="16" height="10" rx="2" fill="hsl(0 70% 45%)" />
<rect x="62" y="50" width="12" height="3" fill="hsl(0 0% 80%)" />
<circle cx="63" cy="59" r="2" fill="hsl(0 0% 8%)" />
<circle cx="73" cy="59" r="2" fill="hsl(0 0% 8%)" />
</>
)}
{shot === "interview" && (
<>
<rect width="160" height="90" fill="hsl(220 20% 14%)" />
<rect x="0" y="55" width="160" height="35" fill="hsl(220 20% 8%)" />
<ellipse cx="80" cy="40" rx="14" ry="16" fill="hsl(30 30% 35%)" />
<ellipse cx="80" cy="32" rx="8" ry="9" fill="hsl(30 40% 55%)" />
<rect x="68" y="55" width="24" height="35" fill="hsl(220 25% 22%)" />
<circle cx="80" cy="70" r="2" fill="hsl(0 80% 50%)" />
</>
)}
{shot === "aerial" && (
<>
<rect width="160" height="90" fill="hsl(200 30% 20%)" />
<path d="M0 50 Q40 40 80 55 T160 50 L160 90 L0 90 Z" fill="hsl(140 20% 25%)" />
<path d="M0 65 Q40 55 80 70 T160 65 L160 90 L0 90 Z" fill="hsl(140 15% 18%)" />
<circle cx="120" cy="20" r="8" fill="hsl(60 30% 60% / 0.4)" />
<rect x="40" y="60" width="3" height="2" fill="white" />
<rect x="80" y="55" width="3" height="2" fill="white" />
<rect x="110" y="62" width="3" height="2" fill="white" />
</>
)}
{shot === "crowd" && (
<>
<rect width="160" height="60" fill={`url(#sky-${seed})`} />
<rect y="60" width="160" height="30" fill="hsl(220 15% 10%)" />
{Array.from({ length: 40 }).map((_, i) => {
const x = (i * 4.5) % 160;
const y = 50 + Math.sin(i * 1.7) * 4;
return <circle key={i} cx={x} cy={y} r="2.5" fill={`hsl(${30 + (i * 13) % 60} 30% ${30 + (i % 3) * 8}%)`} />;
})}
</>
)}
{shot === "trophy" && (
<>
<rect width="160" height="90" fill={`url(#sky-${seed})`} />
<path d="M70 25 L90 25 L88 50 L72 50 Z" fill="hsl(45 80% 55%)" />
<rect x="74" y="50" width="12" height="6" fill="hsl(45 70% 45%)" />
<rect x="70" y="56" width="20" height="4" fill="hsl(45 60% 35%)" />
<path d="M65 35 Q60 30 65 25" fill="none" stroke="hsl(45 80% 55%)" strokeWidth="2" />
<path d="M95 35 Q100 30 95 25" fill="none" stroke="hsl(45 80% 55%)" strokeWidth="2" />
</>
)}
</svg>
);
return <div className="thumb-svg" style={{ background: "var(--bg-1)" }} />;
}
function Waveform({ seed = 1, color = "var(--accent)", className = "" }) {
const bars = 60;
const pts = React.useMemo(() => {
return Array.from({ length: bars }).map((_, i) => {
const x = i / bars;
const n = Math.sin(i * 0.7 + seed) * 0.5 + Math.sin(i * 2.1 + seed * 1.3) * 0.3 + Math.sin(i * 4.3 + seed * 0.7) * 0.2;
return Math.max(0.1, Math.min(1, 0.5 + n * 0.5));
});
@ -131,21 +45,10 @@ function Waveform({ seed = 1, color = "var(--accent)", className = "" }) {
}
function LiveStrip({ seed = 1, count = 8 }) {
const [tick, setTick] = React.useState(0);
React.useEffect(() => {
const i = setInterval(() => setTick(t => t + 1), 2000);
return () => clearInterval(i);
}, []);
return (
<div className="live-strip">
{Array.from({ length: count }).map((_, i) => (
<div
key={`${tick}-${i}`}
className="live-strip-cell"
style={{ background: thumbGrad((seed + i + tick) % 11) }}
>
<FauxFrame seed={(seed + i + tick) % 6} />
</div>
<div key={i} className="live-strip-cell" style={{ background: "var(--bg-1)" }} />
))}
<div className="live-strip-now">
<span className="live-pulse" />