{
  "slug": "olea-restaurant",
  "name": "Olea — Restaurant & Bistro",
  "description": "A coastal Mediterranean restaurant: full-bleed dining-room hero, tabbed menus with dietary badges, chef story, guest and press reviews, a table-booking widget and a wordmark footer.",
  "brief": "a restaurant, bistro, trattoria or wine bar",
  "theme": "olea",
  "author": {
    "name": "CopyPasteUI",
    "github": "copypasteui"
  },
  "sections": [
    "olea-hero",
    "olea-menu",
    "olea-story",
    "olea-reviews",
    "olea-reservations",
    "olea-footer"
  ],
  "images": {
    "thumbnail": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant.jpg",
    "fullPage": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant-full.jpg",
    "preview": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant.webm#t=0.9"
  },
  "isCollection": true,
  "url": "https://copypasteui.dev/templates/olea-restaurant",
  "thumbnailUrl": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant.jpg",
  "fullPageImageUrl": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant-full.jpg",
  "ogImageUrl": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant.jpg",
  "previewVideoUrl": "https://cdn.copypasteui.dev/thumbs/templates/olea-restaurant.webm#t=0.9",
  "prompt": "Build the \"Olea — Restaurant & Bistro\" landing page in this project from CopyPasteUI components (https://copypasteui.dev/templates/olea-restaurant). Everything is free to use in this project.\n\nA coastal Mediterranean restaurant: full-bleed dining-room hero, tabbed menus with dietary badges, chef story, guest and press reviews, a table-booking widget and a wordmark footer.\n\n## Requirements\n- React 18+ with Tailwind CSS.\n- Install dependencies: `npm install lucide-react motion`\n\n## Page structure (top to bottom)\n1. Olea Restaurant Hero — `components/copypasteui/OleaHero.tsx`\n2. Olea Tabbed Menu — `components/copypasteui/OleaMenu.tsx`\n3. Olea Chef Story — `components/copypasteui/OleaStory.tsx`\n4. Olea Guest Reviews — `components/copypasteui/OleaReviews.tsx`\n5. Olea Table Booking — `components/copypasteui/OleaReservations.tsx`\n6. Olea Footer — `components/copypasteui/OleaFooter.tsx`\n\nCreate each file below unchanged, then render them in this order on one page. Afterwards, rewrite the placeholder copy so the whole page tells one consistent story for: a restaurant, bistro, trattoria or wine bar.\n\n## Writing the copy\n- Be specific: prices, opening hours, the street and town, the services by name. If a detail is missing, ask for it or leave a clearly marked gap, and list the gaps at the end. Never invent reviews, ratings, awards or customer numbers.\n- Write the way the owner talks to a customer, in the trade's own words. Use the everyday word: \"use\", not \"utilise\".\n- Headings name what the section is about (\"Opening hours\", \"Prices\"). Buttons say what happens (\"Book a table\", \"Get a quote\"), never \"Learn more\" or \"Submit\".\n- Skip the phrases that make a site sound generated: \"Welcome to\", \"Elevate your\", \"Discover\", \"Look no further\", \"passionate about\", \"trusted by\", \"seamless\", and groups of three adjectives.\n- No em dashes and no exclamation marks. Vary sentence length by writing different sentences, not by chopping them into fragments.\n- Cards, features and FAQ answers can differ in length; they shouldn't all have the same shape.\n- Keep every price, time, condition and warning the owner gives you, at the same strength.\n\nThe footer ends with a small \"Built with CopyPasteUI\" link. It is optional and not part of the licence: keep it if the owner is happy to credit CopyPasteUI (it helps other small businesses find these free templates), or change or remove it if they prefer.\n\n### components/copypasteui/OleaHero.tsx\n```tsx\n// Olea Restaurant Hero from CopyPasteUI — PolyForm Shield 1.0.0: https://polyformproject.org/licenses/shield/1.0.0\n// Required Notice: Copyright 2026 Nidhin Radh P V and the CopyPasteUI contributors (https://copypasteui.dev)\n\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { ArrowRight, Clock, MapPin, Menu, Star } from \"lucide-react\";\n\nconst img = (id: string, w = 1800) => `https://images.unsplash.com/${id}?auto=format&fit=crop&w=${w}&q=80`;\n\nconst ease = [0.22, 1, 0.36, 1] as const;\n\nexport default function OleaHero() {\n  return (\n    <section className=\"relative isolate min-h-[100svh] overflow-hidden bg-primary font-sans text-primary-foreground\">\n      <motion.img\n        initial={{ scale: 1.12 }}\n        animate={{ scale: 1 }}\n        transition={{ duration: 2.4, ease }}\n        src={img(\"photo-1776993298456-98c71c0e177e\", 2200)}\n        alt=\"Olea dining room with leather banquettes set for dinner\"\n        className=\"absolute inset-0 -z-10 size-full object-cover\"\n      />\n      <div className=\"absolute inset-0 -z-10 bg-gradient-to-t from-black/85 via-black/35 to-black/50\" />\n\n      <header className=\"mx-auto flex max-w-7xl items-center justify-between px-6 py-6 text-white\">\n        <nav className=\"hidden flex-1 gap-8 text-sm font-medium md:flex\">\n          {[\"Menu\", \"Wine\", \"Private dining\"].map((l) => (\n            <a key={l} href=\"#\" className=\"opacity-85 hover:opacity-100\">\n              {l}\n            </a>\n          ))}\n        </nav>\n        <a href=\"#\" className=\"font-display text-3xl tracking-[0.2em]\">\n          OLEA\n        </a>\n        <div className=\"flex flex-1 items-center justify-end gap-6 text-sm font-medium\">\n          <a href=\"#\" className=\"hidden opacity-85 hover:opacity-100 md:inline\">\n            Gift cards\n          </a>\n          <a\n            href=\"#reserve\"\n            className=\"hidden rounded-full border border-white/40 px-5 py-2.5 backdrop-blur hover:bg-white hover:text-black sm:inline\"\n          >\n            Book a table\n          </a>\n          <button type=\"button\" aria-label=\"Open menu\" className=\"md:hidden\">\n            <Menu className=\"size-6\" />\n          </button>\n        </div>\n      </header>\n\n      <div className=\"mx-auto flex min-h-[calc(100svh-88px)] max-w-7xl flex-col justify-end px-6 pb-12 text-white\">\n        <motion.p\n          initial={{ opacity: 0, y: 10 }}\n          animate={{ opacity: 1, y: 0 }}\n          transition={{ delay: 0.3, duration: 0.8 }}\n          className=\"text-xs font-semibold tracking-[0.35em] text-white/75 uppercase\"\n        >\n          Coastal Mediterranean · Est. 2014\n        </motion.p>\n        <motion.h1\n          initial={{ opacity: 0, y: 10 }}\n          animate={{ opacity: 1, y: 0 }}\n          transition={{ delay: 0.15, duration: 1.1, ease }}\n          className=\"mt-5 max-w-5xl font-display text-[clamp(3rem,8.5vw,8rem)] leading-[0.92]\"\n        >\n          Long tables, wood fire &amp; the <em className=\"text-white/70 italic\">slow</em> Sunday lunch.\n        </motion.h1>\n\n        <div className=\"mt-10 grid gap-8 border-t border-white/20 pt-8 md:grid-cols-[1.4fr_1fr_1fr_auto] md:items-end\">\n          <p className=\"max-w-md text-white/80\">\n            Charcoal-grilled fish, hand-rolled pasta and olive oil we press ourselves. Seasonal menus from chef Marta Ruiz, served to 64\n            seats on the harbour.\n          </p>\n          <div className=\"flex items-start gap-3 text-sm\">\n            <Clock className=\"mt-0.5 size-4 shrink-0 text-white/60\" />\n            <p>\n              <span className=\"font-semibold\">Tue – Sun</span>\n              <br />\n              <span className=\"text-white/70\">Lunch 12–3 · Dinner 6–11</span>\n            </p>\n          </div>\n          <div className=\"flex items-start gap-3 text-sm\">\n            <MapPin className=\"mt-0.5 size-4 shrink-0 text-white/60\" />\n            <p>\n              <span className=\"font-semibold\">14 Harbour Row</span>\n              <br />\n              <span className=\"text-white/70\">Old Port, Brighton</span>\n            </p>\n          </div>\n          <a\n            href=\"#reserve\"\n            className=\"group inline-flex items-center justify-center gap-2 rounded-full bg-accent px-7 py-4 font-semibold text-accent-foreground\"\n          >\n            Reserve a table <ArrowRight className=\"size-4 transition-transform group-hover:translate-x-1\" />\n          </a>\n        </div>\n      </div>\n\n      <motion.div\n        initial={{ opacity: 0, x: 30 }}\n        animate={{ opacity: 1, x: 0 }}\n        transition={{ delay: 0.9, duration: 0.8 }}\n        className=\"absolute top-28 right-6 hidden w-60 rounded-[var(--radius)] bg-background/95 p-4 text-foreground shadow-2xl backdrop-blur lg:block\"\n      >\n        <div className=\"flex gap-0.5 text-accent\">\n          {Array.from({ length: 5 }).map((_, i) => (\n            <Star key={i} className=\"size-3.5 fill-current\" />\n          ))}\n        </div>\n        <p className=\"mt-2 font-display text-lg leading-snug\">“The best plate of fish on the south coast.”</p>\n        <p className=\"mt-2 text-xs text-muted-foreground\">The Coastal Food Guide, 2026</p>\n      </motion.div>\n    </section>\n  );\n}\n```\n\n### components/copypasteui/OleaMenu.tsx\n```tsx\n// Olea Tabbed Menu from CopyPasteUI — PolyForm Shield 1.0.0: https://polyformproject.org/licenses/shield/1.0.0\n// Required Notice: Copyright 2026 Nidhin Radh P V and the CopyPasteUI contributors (https://copypasteui.dev)\n\"use client\";\n\nimport { useState } from \"react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { Download, Leaf, Wheat } from \"lucide-react\";\n\nconst img = (id: string, w = 1200) => `https://images.unsplash.com/${id}?auto=format&fit=crop&w=${w}&q=80`;\n\ntype Dish = { name: string; note: string; price: string; v?: boolean; gf?: boolean };\n\nconst menus: Record<string, { intro: string; photo: string; alt: string; courses: { title: string; dishes: Dish[] }[] }> = {\n  Dinner: {\n    intro: \"Our evening menu changes with the boats. Plates are made to share; we suggest three or four for two people.\",\n    photo: \"photo-1519233991914-26a44330ccd7\",\n    alt: \"Charred sea bream with crushed potatoes and salsa verde\",\n    courses: [\n      {\n        title: \"To start\",\n        dishes: [\n          { name: \"Focaccia & house oil\", note: \"Rosemary, flaked salt, first-press arbequina\", price: \"6\", v: true },\n          { name: \"Crudo of sea bass\", note: \"Blood orange, fennel pollen, chilli\", price: \"14\", gf: true },\n          { name: \"Burrata\", note: \"Roasted grapes, saba, toasted hazelnuts\", price: \"12\", v: true, gf: true },\n        ],\n      },\n      {\n        title: \"From the fire\",\n        dishes: [\n          { name: \"Whole grilled bream\", note: \"Salsa verde, crushed potatoes, lemon\", price: \"29\", gf: true },\n          { name: \"Lamb shoulder\", note: \"Twelve hours, smoked yoghurt, pickled shallot\", price: \"32\", gf: true },\n          { name: \"Hispi cabbage\", note: \"Anchovy butter, brown crab, crumbs\", price: \"16\" },\n        ],\n      },\n      {\n        title: \"Pasta\",\n        dishes: [\n          { name: \"Pici cacio e pepe\", note: \"Hand-rolled, aged pecorino, Tellicherry pepper\", price: \"17\", v: true },\n          { name: \"Squid ink tagliolini\", note: \"Cuttlefish, ’nduja, parsley\", price: \"21\" },\n        ],\n      },\n    ],\n  },\n  Lunch: {\n    intro: \"Two courses for £24, three for £29, Tuesday to Saturday from noon until three.\",\n    photo: \"photo-1505685509042-16b1b75030cf\",\n    alt: \"Chef finishing a plated starter with a squeeze bottle\",\n    courses: [\n      {\n        title: \"Set lunch\",\n        dishes: [\n          { name: \"Soup of the day\", note: \"With focaccia\", price: \"—\", v: true },\n          { name: \"Mackerel escabeche\", note: \"Saffron, shallot, toasted bread\", price: \"—\" },\n          { name: \"Gnocchi\", note: \"Brown butter, sage, pumpkin seeds\", price: \"—\", v: true },\n          { name: \"Catch of the day\", note: \"Clams, white beans, gremolata\", price: \"—\", gf: true },\n          { name: \"Olive oil cake\", note: \"Crème fraîche, poached quince\", price: \"—\", v: true },\n        ],\n      },\n    ],\n  },\n  Sunday: {\n    intro: \"Family-style Sunday lunch, served from 12:30. £42 a head, children under 10 eat free.\",\n    photo: \"photo-1577106263724-2c8e03bfe9cf\",\n    alt: \"Chef plating greens at the pass\",\n    courses: [\n      {\n        title: \"For the table\",\n        dishes: [\n          { name: \"Antipasti board\", note: \"Cured meats, pickles, marinated olives\", price: \"\" },\n          { name: \"Wood-roast chicken\", note: \"Or porchetta, with all the trimmings\", price: \"\", gf: true },\n          { name: \"Garden plates\", note: \"Whatever the allotment gave us this week\", price: \"\", v: true },\n          { name: \"Tiramisù\", note: \"Made at the table, as big as you dare\", price: \"\", v: true },\n        ],\n      },\n    ],\n  },\n};\n\nexport default function OleaMenu() {\n  const [tab, setTab] = useState<keyof typeof menus>(\"Dinner\");\n  const m = menus[tab]!;\n\n  return (\n    <section id=\"menu\" className=\"bg-background py-24 font-sans text-foreground\">\n      <div className=\"mx-auto max-w-7xl px-6\">\n        <div className=\"flex flex-wrap items-end justify-between gap-6\">\n          <div>\n            <p className=\"text-xs font-semibold tracking-[0.3em] text-primary uppercase\">The menu</p>\n            <h2 className=\"mt-3 font-display text-5xl md:text-6xl\">What’s cooking</h2>\n          </div>\n          <div role=\"tablist\" aria-label=\"Menus\" className=\"flex rounded-full border border-border bg-card p-1\">\n            {Object.keys(menus).map((k) => (\n              <button\n                key={k}\n                role=\"tab\"\n                aria-selected={tab === k}\n                onClick={() => setTab(k)}\n                className={`relative rounded-full px-5 py-2 text-sm font-semibold transition-colors ${tab === k ? \"text-primary-foreground\" : \"text-muted-foreground hover:text-foreground\"}`}\n              >\n                {tab === k && (\n                  <motion.span\n                    layoutId=\"olea-tab\"\n                    className=\"absolute inset-0 -z-0 rounded-full bg-primary\"\n                    transition={{ type: \"spring\", bounce: 0.2, duration: 0.5 }}\n                  />\n                )}\n                <span className=\"relative\">{k}</span>\n              </button>\n            ))}\n          </div>\n        </div>\n\n        <AnimatePresence mode=\"wait\">\n          <motion.div\n            key={tab}\n            initial={{ opacity: 0, y: 10 }}\n            animate={{ opacity: 1, y: 0 }}\n            exit={{ opacity: 0, y: -10 }}\n            transition={{ duration: 0.35 }}\n            className=\"mt-14 grid gap-14 lg:grid-cols-[0.85fr_1.15fr]\"\n          >\n            <div className=\"lg:sticky lg:top-8 lg:self-start\">\n              <div className=\"aspect-[4/5] overflow-hidden rounded-[var(--radius)]\">\n                <img src={img(m.photo)} alt={m.alt} className=\"size-full object-cover\" />\n              </div>\n              <p className=\"mt-5 max-w-sm text-muted-foreground\">{m.intro}</p>\n            </div>\n\n            <div className=\"space-y-12\">\n              {m.courses.map((c) => (\n                <div key={c.title}>\n                  <h3 className=\"font-display text-3xl\">{c.title}</h3>\n                  <ul className=\"mt-5 divide-y divide-border border-t border-border\">\n                    {c.dishes.map((d) => (\n                      <li key={d.name} className=\"group flex items-baseline gap-4 py-5\">\n                        <div className=\"min-w-0 flex-1\">\n                          <p className=\"flex flex-wrap items-center gap-2 text-lg font-semibold transition-colors group-hover:text-accent\">\n                            {d.name}\n                            {d.v && (\n                              <span title=\"Vegetarian\" className=\"grid size-5 place-items-center rounded-full bg-secondary\">\n                                <Leaf className=\"size-3\" aria-label=\"Vegetarian\" />\n                              </span>\n                            )}\n                            {d.gf && (\n                              <span title=\"Gluten free\" className=\"grid size-5 place-items-center rounded-full bg-secondary\">\n                                <Wheat className=\"size-3\" aria-label=\"Gluten free\" />\n                              </span>\n                            )}\n                          </p>\n                          <p className=\"mt-1 text-sm text-muted-foreground\">{d.note}</p>\n                        </div>\n                        {d.price && <span className=\"font-display text-xl tabular-nums\">{d.price === \"—\" ? \"—\" : `£${d.price}`}</span>}\n                      </li>\n                    ))}\n                  </ul>\n                </div>\n              ))}\n              <div className=\"flex flex-wrap items-center gap-x-6 gap-y-3 text-sm text-muted-foreground\">\n                <span className=\"inline-flex items-center gap-2\">\n                  <Leaf className=\"size-4\" /> Vegetarian\n                </span>\n                <span className=\"inline-flex items-center gap-2\">\n                  <Wheat className=\"size-4\" /> Gluten free\n                </span>\n                <a\n                  href=\"#\"\n                  className=\"ml-auto inline-flex items-center gap-2 font-semibold text-foreground underline-offset-4 hover:underline\"\n                >\n                  <Download className=\"size-4\" /> Full menu &amp; allergens (PDF)\n                </a>\n              </div>\n            </div>\n          </motion.div>\n        </AnimatePresence>\n      </div>\n    </section>\n  );\n}\n```\n\n### components/copypasteui/OleaStory.tsx\n```tsx\n// Olea Chef Story from CopyPasteUI — PolyForm Shield 1.0.0: https://polyformproject.org/licenses/shield/1.0.0\n// Required Notice: Copyright 2026 Nidhin Radh P V and the CopyPasteUI contributors (https://copypasteui.dev)\n\"use client\";\n\nimport { motion } from \"motion/react\";\n\nconst img = (id: string, w = 1400) => `https://images.unsplash.com/${id}?auto=format&fit=crop&w=${w}&q=80`;\n\nconst facts = [\n  { n: \"64\", l: \"seats on the harbour\" },\n  { n: \"11\", l: \"local boats we buy from\" },\n  { n: \"2,400\", l: \"litres of our own olive oil a year\" },\n];\n\nconst strip = [\n  { id: \"photo-1578425570232-bf51f753dd5e\", cap: \"Service, 7:40pm\" },\n  { id: \"photo-1564844536308-50b114a1d946\", cap: \"Seasoning the greens\" },\n  { id: \"photo-1552960226-639240203497\", cap: \"The back room, lit for dinner\" },\n  { id: \"photo-1653259038915-7cf0b7a4dd6c\", cap: \"Private dining, up to 18\" },\n  { id: \"photo-1776993298422-5b7df704c2c1\", cap: \"Lunch light\" },\n];\n\nexport default function OleaStory() {\n  return (\n    <section className=\"overflow-hidden bg-secondary py-24 font-sans text-secondary-foreground\">\n      <div className=\"mx-auto grid max-w-7xl gap-14 px-6 lg:grid-cols-[1fr_1.1fr] lg:items-center\">\n        <motion.div\n          initial={{ opacity: 0, y: 10 }}\n          whileInView={{ opacity: 1, y: 0 }}\n          viewport={{ once: true, margin: \"-80px\" }}\n          transition={{ duration: 0.8 }}\n          className=\"relative\"\n        >\n          <div className=\"aspect-[4/5] w-4/5 overflow-hidden rounded-[var(--radius)]\">\n            <img\n              src={img(\"photo-1577106263724-2c8e03bfe9cf\")}\n              alt=\"Chef Marta Ruiz plating at the pass\"\n              className=\"size-full object-cover\"\n            />\n          </div>\n          <div className=\"absolute right-0 -bottom-8 w-1/2 overflow-hidden rounded-[var(--radius)] border-8 border-secondary shadow-2xl\">\n            <img\n              src={img(\"photo-1519233991914-26a44330ccd7\", 800)}\n              alt=\"Grilled bream on a grey plate\"\n              className=\"aspect-square w-full object-cover\"\n            />\n          </div>\n        </motion.div>\n\n        <div>\n          <p className=\"text-xs font-semibold tracking-[0.3em] text-primary uppercase\">Our story</p>\n          <h2 className=\"mt-4 font-display text-5xl leading-[1.02] md:text-6xl\">\n            A fisherman’s daughter, a wood oven and <em>ten years</em> of Sundays.\n          </h2>\n          <div className=\"mt-8 space-y-4 text-lg text-muted-foreground\">\n            <p>\n              Marta grew up gutting her father’s catch on the quay at Cádiz. She opened Olea in an old net loft with one oven, eight tables\n              and no sign on the door.\n            </p>\n            <p>\n              We still cook over oak and olive wood, still buy whatever the boats bring in, and still close on Mondays so the team can eat\n              dinner with their families.\n            </p>\n          </div>\n          <dl className=\"mt-10 grid grid-cols-3 gap-6 border-t border-border pt-8\">\n            {facts.map((f) => (\n              <div key={f.l}>\n                <dt className=\"font-display text-4xl text-foreground md:text-5xl\">{f.n}</dt>\n                <dd className=\"mt-1 text-sm text-muted-foreground\">{f.l}</dd>\n              </div>\n            ))}\n          </dl>\n          <p className=\"mt-10 font-display text-2xl text-foreground italic\">— Marta Ruiz, chef &amp; owner</p>\n        </div>\n      </div>\n\n      <div className=\"mt-24 flex w-max [animation:olea-strip_60s_linear_infinite] gap-5 px-6 hover:[animation-play-state:paused] motion-reduce:animate-none\">\n        {[...strip, ...strip].map((s, i) => (\n          <figure key={i} className=\"w-72 shrink-0 md:w-96\" aria-hidden={i >= strip.length}>\n            <div className=\"aspect-[4/3] overflow-hidden rounded-[var(--radius)]\">\n              <img\n                src={img(s.id, 900)}\n                alt={i < strip.length ? s.cap : \"\"}\n                className=\"size-full object-cover transition-transform duration-700 hover:scale-105\"\n              />\n            </div>\n            <figcaption className=\"mt-3 text-sm text-muted-foreground\">{s.cap}</figcaption>\n          </figure>\n        ))}\n      </div>\n      <style>{`@keyframes olea-strip { to { transform: translateX(-50%); } }`}</style>\n    </section>\n  );\n}\n```\n\n### components/copypasteui/OleaReviews.tsx\n```tsx\n// Olea Guest Reviews from CopyPasteUI — PolyForm Shield 1.0.0: https://polyformproject.org/licenses/shield/1.0.0\n// Required Notice: Copyright 2026 Nidhin Radh P V and the CopyPasteUI contributors (https://copypasteui.dev)\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { Star } from \"lucide-react\";\n\nconst reviews = [\n  {\n    quote: \"We came for the bream and stayed four hours. The kind of place you start planning to come back to before the bill arrives.\",\n    name: \"Hannah & Joe\",\n    meta: \"Anniversary dinner · Google\",\n  },\n  {\n    quote: \"Proper hospitality. They remembered my dad’s birthday from last year and brought out a candle in the olive oil cake.\",\n    name: \"Priya S.\",\n    meta: \"Sunday lunch · OpenTable\",\n  },\n  {\n    quote: \"The cacio e pepe alone is worth the train from London. Ask to sit at the counter and watch the fire.\",\n    name: \"Tom W.\",\n    meta: \"Dinner for two · Tripadvisor\",\n  },\n];\n\nconst press = [\n  { name: \"The Coastal Food Guide\", award: \"Best Seafood 2026\" },\n  { name: \"Harbour Times\", award: \"★★★★★\" },\n  { name: \"Good Table Awards\", award: \"Top 50 UK\" },\n  { name: \"Sussex Life\", award: \"Restaurant of the Year\" },\n];\n\nexport default function OleaReviews() {\n  const [i, setI] = useState(0);\n  useEffect(() => {\n    const t = setInterval(() => setI((n) => (n + 1) % reviews.length), 6500);\n    return () => clearInterval(t);\n  }, []);\n  const r = reviews[i]!;\n\n  return (\n    <section className=\"bg-primary py-24 font-sans text-primary-foreground\">\n      <div className=\"mx-auto max-w-5xl px-6 text-center\">\n        <div className=\"inline-flex items-center gap-3 rounded-full border border-primary-foreground/20 px-4 py-2 text-sm\">\n          <span className=\"flex gap-0.5\">\n            {Array.from({ length: 5 }).map((_, k) => (\n              <Star key={k} className=\"size-3.5 fill-current\" />\n            ))}\n          </span>\n          4.7 from 2,180 guest reviews\n        </div>\n\n        <div className=\"relative mt-12 min-h-[15rem] md:min-h-[12rem]\">\n          <AnimatePresence mode=\"wait\">\n            <motion.figure\n              key={i}\n              initial={{ opacity: 0, filter: \"blur(6px)\", y: 10 }}\n              animate={{ opacity: 1, filter: \"blur(0px)\", y: 0 }}\n              exit={{ opacity: 0, filter: \"blur(6px)\", y: -10 }}\n              transition={{ duration: 0.6 }}\n            >\n              <blockquote className=\"font-display text-3xl leading-tight md:text-5xl\">“{r.quote}”</blockquote>\n              <figcaption className=\"mt-8 text-sm\">\n                <span className=\"font-semibold\">{r.name}</span>\n                <span className=\"opacity-90\"> — {r.meta}</span>\n              </figcaption>\n            </motion.figure>\n          </AnimatePresence>\n        </div>\n\n        <div className=\"mt-10 flex justify-center gap-2\">\n          {reviews.map((_, k) => (\n            <button\n              key={k}\n              type=\"button\"\n              aria-label={`Show review ${k + 1}`}\n              aria-current={k === i}\n              onClick={() => setI(k)}\n              className=\"h-1.5 rounded-full bg-primary-foreground transition-all\"\n              style={{ width: k === i ? 32 : 10, opacity: k === i ? 1 : 0.35 }}\n            />\n          ))}\n        </div>\n      </div>\n\n      <div className=\"mx-auto mt-20 grid max-w-6xl grid-cols-2 gap-px overflow-hidden border-y border-primary-foreground/15 px-6 md:grid-cols-4\">\n        {press.map((p) => (\n          <div key={p.name} className=\"px-4 py-8 text-center\">\n            <p className=\"font-display text-xl\">{p.name}</p>\n            <p className=\"mt-1 text-xs tracking-[0.2em] uppercase opacity-90\">{p.award}</p>\n          </div>\n        ))}\n      </div>\n    </section>\n  );\n}\n```\n\n### components/copypasteui/OleaReservations.tsx\n```tsx\n// Olea Table Booking from CopyPasteUI — PolyForm Shield 1.0.0: https://polyformproject.org/licenses/shield/1.0.0\n// Required Notice: Copyright 2026 Nidhin Radh P V and the CopyPasteUI contributors (https://copypasteui.dev)\n\"use client\";\n\nimport { useState } from \"react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { Check, Clock, MapPin, Minus, Phone, Plus, Users } from \"lucide-react\";\n\nconst days = [\n  { d: \"Thu\", n: \"22\" },\n  { d: \"Fri\", n: \"23\" },\n  { d: \"Sat\", n: \"24\" },\n  { d: \"Sun\", n: \"25\" },\n  { d: \"Tue\", n: \"27\" },\n  { d: \"Wed\", n: \"28\" },\n];\nconst times = [\"18:00\", \"18:30\", \"19:00\", \"19:30\", \"20:00\", \"20:30\", \"21:00\", \"21:30\"];\nconst full = new Set([\"19:30\", \"20:00\"]);\n\nexport default function OleaReservations() {\n  const [guests, setGuests] = useState(2);\n  const [day, setDay] = useState(1);\n  const [time, setTime] = useState(\"19:00\");\n  const [done, setDone] = useState(false);\n\n  return (\n    <section id=\"reserve\" className=\"bg-background py-24 font-sans text-foreground\">\n      <div className=\"mx-auto grid max-w-7xl gap-12 px-6 lg:grid-cols-[1.2fr_0.8fr]\">\n        <div className=\"rounded-[calc(var(--radius)*3)] border border-border bg-card p-6 text-card-foreground shadow-xl shadow-foreground/5 md:p-10\">\n          <p className=\"text-xs font-semibold tracking-[0.3em] text-primary uppercase\">Reservations</p>\n          <h2 className=\"mt-3 font-display text-4xl md:text-5xl\">Book a table</h2>\n\n          <AnimatePresence mode=\"wait\">\n            {done ? (\n              <motion.div\n                key=\"done\"\n                initial={{ opacity: 0, scale: 0.96 }}\n                animate={{ opacity: 1, scale: 1 }}\n                exit={{ opacity: 0 }}\n                className=\"py-16 text-center\"\n              >\n                <div className=\"mx-auto grid size-16 place-items-center rounded-full bg-primary text-primary-foreground\">\n                  <Check className=\"size-8\" />\n                </div>\n                <p className=\"mt-6 font-display text-3xl\">\n                  See you {days[day]!.d} {days[day]!.n} at {time}.\n                </p>\n                <p className=\"mt-2 text-muted-foreground\">Table for {guests}. A confirmation is on its way to your inbox.</p>\n                <button type=\"button\" onClick={() => setDone(false)} className=\"mt-8 text-sm font-semibold underline underline-offset-4\">\n                  Change booking\n                </button>\n              </motion.div>\n            ) : (\n              <motion.form\n                key=\"form\"\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{ opacity: 0 }}\n                onSubmit={(e) => {\n                  e.preventDefault();\n                  setDone(true);\n                }}\n                className=\"mt-8 space-y-8\"\n              >\n                <div className=\"flex items-center justify-between gap-4 rounded-[var(--radius)] bg-muted p-4\">\n                  <span className=\"inline-flex items-center gap-2 font-semibold\">\n                    <Users className=\"size-5\" /> Guests\n                  </span>\n                  <div className=\"flex items-center gap-4\">\n                    <button\n                      type=\"button\"\n                      aria-label=\"Fewer guests\"\n                      onClick={() => setGuests((g) => Math.max(1, g - 1))}\n                      className=\"grid size-9 place-items-center rounded-full border border-border bg-card hover:border-foreground\"\n                    >\n                      <Minus className=\"size-4\" />\n                    </button>\n                    <span className=\"w-6 text-center font-display text-2xl tabular-nums\" aria-live=\"polite\">\n                      {guests}\n                    </span>\n                    <button\n                      type=\"button\"\n                      aria-label=\"More guests\"\n                      onClick={() => setGuests((g) => Math.min(8, g + 1))}\n                      className=\"grid size-9 place-items-center rounded-full border border-border bg-card hover:border-foreground\"\n                    >\n                      <Plus className=\"size-4\" />\n                    </button>\n                  </div>\n                </div>\n\n                <fieldset>\n                  <legend className=\"text-sm font-semibold\">October</legend>\n                  <div className=\"mt-3 grid grid-cols-3 gap-2 sm:grid-cols-6\">\n                    {days.map((d, k) => (\n                      <button\n                        key={d.n}\n                        type=\"button\"\n                        aria-pressed={day === k}\n                        onClick={() => setDay(k)}\n                        className={`rounded-[var(--radius)] border py-3 text-center transition ${day === k ? \"border-primary bg-primary text-primary-foreground\" : \"border-border hover:border-foreground\"}`}\n                      >\n                        <span className=\"block text-xs opacity-90\">{d.d}</span>\n                        <span className=\"block font-display text-2xl\">{d.n}</span>\n                      </button>\n                    ))}\n                  </div>\n                </fieldset>\n\n                <fieldset>\n                  <legend className=\"text-sm font-semibold\">Time</legend>\n                  <div className=\"mt-3 grid grid-cols-4 gap-2\">\n                    {times.map((t) => {\n                      const off = full.has(t);\n                      return (\n                        <button\n                          key={t}\n                          type=\"button\"\n                          disabled={off}\n                          aria-pressed={time === t}\n                          onClick={() => setTime(t)}\n                          className={`rounded-full border py-2.5 text-sm font-semibold tabular-nums transition disabled:cursor-not-allowed disabled:line-through disabled:opacity-40 ${time === t ? \"border-accent bg-accent text-accent-foreground\" : \"border-border hover:border-foreground\"}`}\n                        >\n                          {t}\n                        </button>\n                      );\n                    })}\n                  </div>\n                </fieldset>\n\n                <div className=\"grid gap-3 sm:grid-cols-2\">\n                  <input\n                    required\n                    placeholder=\"Full name\"\n                    aria-label=\"Full name\"\n                    className=\"rounded-[var(--radius)] border border-border bg-background px-4 py-3 outline-none focus:border-ring\"\n                  />\n                  <input\n                    required\n                    type=\"email\"\n                    placeholder=\"Email\"\n                    aria-label=\"Email\"\n                    className=\"rounded-[var(--radius)] border border-border bg-background px-4 py-3 outline-none focus:border-ring\"\n                  />\n                  <textarea\n                    placeholder=\"Allergies, high chair, celebrating something?\"\n                    aria-label=\"Notes\"\n                    rows={2}\n                    className=\"rounded-[var(--radius)] border border-border bg-background px-4 py-3 outline-none focus:border-ring sm:col-span-2\"\n                  />\n                </div>\n\n                <button\n                  type=\"submit\"\n                  className=\"w-full rounded-full bg-primary py-4 font-semibold text-primary-foreground hover:opacity-90\"\n                >\n                  Reserve for {guests} · {days[day]!.d} {days[day]!.n}, {time}\n                </button>\n                <p className=\"text-center text-xs text-muted-foreground\">Parties of 9 or more: call us or ask about private dining.</p>\n              </motion.form>\n            )}\n          </AnimatePresence>\n        </div>\n\n        <div className=\"flex flex-col gap-6\">\n          <div className=\"relative aspect-[4/3] overflow-hidden rounded-[calc(var(--radius)*3)] bg-muted lg:flex-1\">\n            <svg viewBox=\"0 0 400 300\" className=\"absolute inset-0 size-full text-border\" aria-hidden>\n              <rect width=\"400\" height=\"300\" className=\"fill-muted\" />\n              <path d=\"M0 210 C 90 190, 140 240, 230 215 S 360 170, 400 190 L400 300 L0 300Z\" className=\"fill-secondary\" />\n              {[40, 100, 160].map((y) => (\n                <path key={y} d={`M0 ${y} L400 ${y - 30}`} stroke=\"currentColor\" strokeWidth=\"10\" />\n              ))}\n              {[80, 210, 320].map((x) => (\n                <path key={x} d={`M${x} 0 L${x + 30} 210`} stroke=\"currentColor\" strokeWidth=\"10\" />\n              ))}\n            </svg>\n            <div className=\"absolute top-[42%] left-1/2 -translate-x-1/2 -translate-y-full\">\n              <span className=\"relative grid size-12 place-items-center rounded-full bg-accent font-display text-lg text-accent-foreground shadow-xl\">\n                O\n              </span>\n              <span className=\"absolute inset-0 -z-10 animate-ping rounded-full bg-accent/40\" />\n            </div>\n            <span className=\"absolute bottom-4 left-4 rounded-full bg-card px-3 py-1.5 text-xs font-semibold text-card-foreground shadow\">\n              Harbour, 2 min walk from the pier\n            </span>\n          </div>\n          <ul className=\"space-y-4 rounded-[calc(var(--radius)*3)] bg-secondary p-6 text-secondary-foreground\">\n            <li className=\"flex gap-3\">\n              <MapPin className=\"mt-0.5 size-5 shrink-0\" />\n              <span>\n                14 Harbour Row, Old Port\n                <br />\n                Brighton BN1 1PT\n              </span>\n            </li>\n            <li className=\"flex gap-3\">\n              <Clock className=\"mt-0.5 size-5 shrink-0\" />\n              <span>\n                Tue–Sat 12–3 &amp; 6–11\n                <br />\n                Sun 12:30–5 · Closed Mon\n              </span>\n            </li>\n            <li className=\"flex gap-3\">\n              <Phone className=\"mt-0.5 size-5 shrink-0\" />\n              <a href=\"tel:+441273000000\" className=\"font-semibold hover:underline\">\n                01273 000 000\n              </a>\n            </li>\n          </ul>\n        </div>\n      </div>\n    </section>\n  );\n}\n```\n\n### components/copypasteui/OleaFooter.tsx\n```tsx\n// Olea Footer from CopyPasteUI — PolyForm Shield 1.0.0: https://polyformproject.org/licenses/shield/1.0.0\n// Required Notice: Copyright 2026 Nidhin Radh P V and the CopyPasteUI contributors (https://copypasteui.dev)\n\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { ArrowUpRight, AtSign, Gift } from \"lucide-react\";\n\nconst cols = [\n  { title: \"Visit\", links: [\"Menu\", \"Wine list\", \"Sunday lunch\", \"Private dining\", \"Gift cards\"] },\n  { title: \"Olea\", links: [\"Our story\", \"Suppliers\", \"Careers\", \"Press\", \"Contact\"] },\n];\n\nexport default function OleaFooter() {\n  return (\n    <footer className=\"overflow-hidden bg-primary font-sans text-primary-foreground\">\n      <div className=\"mx-auto max-w-7xl px-6 pt-20\">\n        <div className=\"grid gap-12 sm:grid-cols-2 lg:grid-cols-[1.4fr_1fr_1fr_1.2fr]\">\n          <div>\n            <p className=\"font-display text-3xl leading-tight\">Supper club on the first Friday of every month.</p>\n            <form\n              onSubmit={(e) => e.preventDefault()}\n              className=\"mt-6 flex max-w-sm overflow-hidden rounded-full border border-primary-foreground/30\"\n            >\n              <input\n                type=\"email\"\n                required\n                placeholder=\"Your email\"\n                aria-label=\"Email\"\n                className=\"min-w-0 flex-1 bg-transparent px-5 py-3 text-sm outline-none placeholder:text-primary-foreground/90\"\n              />\n              <button type=\"submit\" className=\"bg-primary-foreground px-5 text-sm font-semibold text-primary\">\n                Join\n              </button>\n            </form>\n          </div>\n          {cols.map((c) => (\n            <nav key={c.title} aria-label={c.title}>\n              <p className=\"text-xs font-semibold tracking-[0.25em] uppercase opacity-90\">{c.title}</p>\n              <ul className=\"mt-5 space-y-3\">\n                {c.links.map((l) => (\n                  <li key={l}>\n                    <a href=\"#\" className=\"hover:underline\">\n                      {l}\n                    </a>\n                  </li>\n                ))}\n              </ul>\n            </nav>\n          ))}\n          <div className=\"space-y-5 text-sm\">\n            <p className=\"text-xs font-semibold tracking-[0.25em] uppercase opacity-90\">Find us</p>\n            <p>\n              14 Harbour Row, Old Port\n              <br />\n              Brighton BN1 1PT\n            </p>\n            <p>\n              hello@olea.example\n              <br />\n              01273 000 000\n            </p>\n            <div className=\"flex gap-3\">\n              <a\n                href=\"#\"\n                className=\"inline-flex items-center gap-1.5 rounded-full border border-primary-foreground/30 px-3 py-1.5 hover:bg-primary-foreground hover:text-primary\"\n              >\n                <AtSign className=\"size-3.5\" /> Instagram\n              </a>\n              <a\n                href=\"#\"\n                className=\"inline-flex items-center gap-1.5 rounded-full border border-primary-foreground/30 px-3 py-1.5 hover:bg-primary-foreground hover:text-primary\"\n              >\n                <Gift className=\"size-3.5\" /> Gifts\n              </a>\n            </div>\n          </div>\n        </div>\n\n        <a\n          href=\"#reserve\"\n          className=\"group mt-16 flex items-center justify-between gap-6 border-y border-primary-foreground/20 py-6 text-xl font-semibold\"\n        >\n          Reserve your table <ArrowUpRight className=\"size-6 transition-transform group-hover:translate-x-1 group-hover:-translate-y-1\" />\n        </a>\n      </div>\n\n      <motion.p\n        initial={{ y: \"30%\", opacity: 0 }}\n        whileInView={{ y: \"0%\", opacity: 1 }}\n        viewport={{ once: true }}\n        transition={{ duration: 1.2, ease: [0.22, 1, 0.36, 1] }}\n        aria-hidden\n        className=\"text-center font-display text-[30vw] leading-[0.8] tracking-[0.05em] opacity-95 select-none\"\n      >\n        OLEA\n      </motion.p>\n      <div className=\"mx-auto flex max-w-7xl flex-wrap justify-between gap-3 px-6 py-6 text-xs opacity-90\">\n        <p>\n          © 2026 Olea Kitchen Ltd.{\" \"}\n          {/* Optional credit, for a link back to CopyPasteUI. Keep it, change it or remove it: it is not a licence requirement. */}· Built\n          with{\" \"}\n          <a href=\"https://copypasteui.dev\" className=\"underline underline-offset-2 hover:opacity-80\">\n            CopyPasteUI\n          </a>\n        </p>\n        <p>Allergens · Privacy · Accessibility</p>\n      </div>\n    </footer>\n  );\n}\n```\n\n{{THEME}}"
}
