diff --git a/wp-content/themes/moonshine/app/components/sections/SectionHeroSplit.global.vue b/wp-content/themes/moonshine/app/components/sections/SectionHeroSplit.global.vue
index 4455aed..962e4b9 100644
--- a/wp-content/themes/moonshine/app/components/sections/SectionHeroSplit.global.vue
+++ b/wp-content/themes/moonshine/app/components/sections/SectionHeroSplit.global.vue
@@ -34,7 +34,7 @@ const classes = tvSectionHeroSplit({
diff --git a/wp-content/themes/moonshine/app/utils/acf-media.ts b/wp-content/themes/moonshine/app/utils/acf-media.ts
new file mode 100644
index 0000000..e7f779f
--- /dev/null
+++ b/wp-content/themes/moonshine/app/utils/acf-media.ts
@@ -0,0 +1,29 @@
+import type { AcfMediaFragment } from "#graphql/operations";
+import * as z from "zod";
+
+export const acfImageSchema = z.object({
+ src: z.url(),
+ alt: z.string(),
+ mediaDetails: z.object({
+ width: z.number(),
+ height: z.number(),
+ }),
+ objectPosition: z.string().optional().default("center"),
+});
+
+export const acfMediaSchema = z.object({
+ image: z.object({
+ node: acfImageSchema,
+ }),
+ aspectRatio: z.enum(["square", "video", "portrait", "auto"]).optional().default("auto"),
+ objectFit: z.enum(["cover", "contain"]).optional().default("cover"),
+});
+
+export function parseAcfMedia(data?: Partial) {
+ try {
+ return acfMediaSchema.parse(data);
+ }
+ catch {
+ return undefined;
+ }
+}