Zero cooks, all machine. A robotic kitchen grills, assembles, and plates your tasty menu in real time — watch it happen live, from
diff --git a/src/components/ordering/MenuBackdrop.module.scss b/src/components/ordering/MenuBackdrop.module.scss
index 7d9e8d5..e194e38 100644
--- a/src/components/ordering/MenuBackdrop.module.scss
+++ b/src/components/ordering/MenuBackdrop.module.scss
@@ -1,7 +1,17 @@
@use '../../styles/variables' as *;
+@keyframes menu-backdrop-float {
+ 0%,
+ 100% {
+ transform: translateY(0) rotate(var(--icon-rotate, 0deg));
+ }
+ 50% {
+ transform: translateY(-6px) rotate(calc(var(--icon-rotate, 0deg) + 6deg));
+ }
+}
+
.backdrop {
- position: fixed;
+ position: absolute;
inset: 0;
z-index: -1;
overflow: hidden;
@@ -11,7 +21,12 @@
.icon {
position: absolute;
color: $color-primary;
- opacity: 0.08;
+ opacity: 0.16;
+ transform: rotate(var(--icon-rotate, 0deg));
+
+ @media (prefers-reduced-motion: no-preference) {
+ animation: menu-backdrop-float 5s ease-in-out infinite;
+ }
svg {
width: 100%;
diff --git a/src/components/ordering/MenuBackdrop.tsx b/src/components/ordering/MenuBackdrop.tsx
index 538ad43..5670449 100644
--- a/src/components/ordering/MenuBackdrop.tsx
+++ b/src/components/ordering/MenuBackdrop.tsx
@@ -1,3 +1,5 @@
+import type { CSSProperties } from 'react'
+
import styles from './MenuBackdrop.module.scss'
const PizzaIcon = () => (
@@ -47,20 +49,17 @@ const ICONS = [PizzaIcon, BurgerIcon, FriesIcon]
// Fixed, hand-placed positions rather than random ones — random values would
// differ between the server-rendered and first client-rendered HTML and
-// trigger a hydration mismatch.
+// trigger a hydration mismatch. Positioned as percentages of the containing
+// card, not the viewport, so this only ever covers whatever box renders it.
const PLACEMENTS = [
- { top: '6%', left: '6%', size: 72, rotate: -14 },
- { top: '14%', left: '86%', size: 56, rotate: 20 },
- { top: '30%', left: '46%', size: 64, rotate: -6 },
- { top: '46%', left: '10%', size: 52, rotate: 10 },
- { top: '58%', left: '90%', size: 68, rotate: -18 },
- { top: '72%', left: '30%', size: 58, rotate: 14 },
- { top: '82%', left: '68%', size: 60, rotate: -8 },
- { top: '4%', left: '40%', size: 44, rotate: 8 },
- { top: '38%', left: '78%', size: 46, rotate: -22 },
- { top: '64%', left: '52%', size: 40, rotate: 16 },
- { top: '90%', left: '12%', size: 50, rotate: -10 },
- { top: '20%', left: '20%', size: 42, rotate: 24 },
+ { top: '10%', left: '8%', size: 32, rotate: -14, delay: 0 },
+ { top: '14%', left: '82%', size: 26, rotate: 18, delay: 0.5 },
+ { top: '40%', left: '20%', size: 24, rotate: 8, delay: 1.1 },
+ { top: '55%', left: '80%', size: 30, rotate: -10, delay: 0.3 },
+ { top: '78%', left: '14%', size: 26, rotate: 16, delay: 1.6 },
+ { top: '82%', left: '58%', size: 22, rotate: -20, delay: 0.8 },
+ { top: '22%', left: '48%', size: 20, rotate: 6, delay: 1.3 },
+ { top: '62%', left: '44%', size: 24, rotate: -6, delay: 0.2 },
]
export const MenuBackdrop = () => (
@@ -71,13 +70,16 @@ export const MenuBackdrop = () => (
Your basket is empty
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
index 7e9272e..d1f4018 100644
--- a/src/routes/index.tsx
+++ b/src/routes/index.tsx
@@ -1,6 +1,5 @@
import { createFileRoute } from '@tanstack/react-router'
-import { MenuBackdrop } from '#/components/ordering/MenuBackdrop.tsx'
import { MenuList } from '#/components/ordering/MenuList.tsx'
import { useBasket } from '#/lib/basket.tsx'
import { getBrand } from '#/server/brand.ts'
@@ -14,7 +13,6 @@ const OrderingPage = () => {
return (
Zero cooks, all machine. A robotic kitchen grills, assembles, and
plates your tasty menu in real time — watch it happen live, from