{selectedMap && (
setSelectedMap(null)}
imageSrc={selectedMap.image}
label={selectedMap.label}
rotateMessage={t("expo.rotateDevice")}
/>
)}
>
);
}
/** Venue map card: the map SVG rendered transparent over the page background. */
function MapCard({ image, label }: { image: string; label: string }) {
return (
);
}
/**
* Photo tile in the gallery band: the image is faded over the dark background
* (as in the design) with a large caption. Caption alignment is configurable so
* the middle tile can sit bottom-right like the mockup.
*/
function FadedPhoto({
image,
caption,
align = "left",
valign = "center",
}: {
image: string;
caption: string;
align?: "left" | "right";
valign?: "center" | "bottom";
}) {
return (
{caption}
);
}
/** Skewed section heading (no rule underneath — sections are split by DIVIDER). */
function SectionHeading({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
/**
* One showcase card: a cyan-bordered logo box above a linked title and a
* studio/team line. Logos render object-contain; screenshots (`cover`) fill the
* box. Teams without a logo yet fall back to their name set inside the box.
*/
function GameCard({
image,
title,
subtitle,
url,
cover = false,
}: {
image?: string;
title: string;
subtitle: string;
url?: string;
cover?: boolean;
}) {
const titleEl = url ? (
{title}
) : (
{title}
);
return (
{image ? (
) : (
{title}
)}
{titleEl}
{subtitle}
);
}
export default function Expo() {
const t = useTranslations();
return (