Crumbelle UI Template - Let's templates
Crumbelle preview 1
Free
0 4

Crumbelle

By Luca Moretti

Crumbelle is a cheerful, checkerboard bakery template for pastry shops and dessert delivery, with a tilted cake hero, product boxes, an ingredients spotlight, a build-your-box configurator, a delivery checker and an FAQ.

Live Demo
crumbelle-tailwind.html
<%# letstemplates: access=free category=food-restaurant %>
<!DOCTYPE html>
<html lang="en">
<head>
  <script>
    window.FontAwesomeConfig = { autoReplaceSvg: 'nest' };
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Crumbelle | Tailwind CSS Food &amp; Restaurant Template</title>
  <meta name="description" content="Crumbelle is a cheerful, checkerboard Tailwind CSS bakery template for pastry shops and dessert delivery, with a tilted cake hero, product boxes, an ingredients spotlight, a build-your-box configurator, a delivery checker and an FAQ.">
  <meta name="keywords" content="Crumbelle, Tailwind CSS template, HTML website template, bakery template, pastry shop website, dessert delivery, cake shop, food and restaurant template, online bakery">
  <meta name="author" content="Let's templates">
  <link rel="canonical" href="">

  <meta property="og:type" content="product">
  <meta property="og:site_name" content="Let's templates">
  <meta property="og:locale" content="en_US">
  <meta property="og:url" content="">
  <meta property="og:title" content="Crumbelle | Tailwind CSS Food &amp; Restaurant Template">
  <meta property="og:description" content="A cheerful, checkerboard Tailwind CSS bakery template with product boxes, a build-your-box configurator and a delivery checker.">
  <meta property="og:image" content="">
  <meta property="og:image:alt" content="Crumbelle template preview">

  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:url" content="">
  <meta name="twitter:title" content="Crumbelle | Tailwind CSS Food &amp; Restaurant Template">
  <meta name="twitter:description" content="A cheerful, checkerboard Tailwind CSS bakery template with product boxes, a build-your-box configurator and a delivery checker.">
  <meta name="twitter:image" content="">
  <meta name="twitter:image:alt" content="Crumbelle template preview">
  <script src="https://cdn.tailwindcss.com/3.4.17"></script>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Chewy&family=Poppins:wght@400;500;600&display=swap" rel="stylesheet">
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: { blush: '#fdecec', rose: { DEFAULT: '#f7a6a8', deep: '#ef7f86' }, mint: '#b2dcc7', pistachio: '#e1e8c4', peach: '#fcd2b4', ink: '#141414' },
          fontFamily: { sans: ['Poppins', 'sans-serif'], display: ['Chewy', 'cursive'] }
        }
      }
    }
  </script>
  <style>
    @view-transition { navigation: auto; }
    ::view-transition-old(root) { animation: 180ms ease-out both page-fade-out; }
    ::view-transition-new(root) { animation: 220ms ease-in both page-fade-in; }
    @keyframes page-fade-out { to { opacity: 0; } }
    @keyframes page-fade-in { from { opacity: 0; } }
    html { scroll-behavior: smooth; }
    [hidden] { display: none !important; }
    .checker { background-color: #e1e8c4; background-image: conic-gradient(#d3e6c6 25%, transparent 0 50%, #d3e6c6 0 75%, transparent 0); background-size: 3.5rem 3.5rem; }
    .checker-mint { background-color: #c6e4d2; background-image: conic-gradient(#e6efcf 25%, transparent 0 50%, #e6efcf 0 75%, transparent 0); background-size: 3.5rem 3.5rem; }
    .btn-pop { box-shadow: 0 3px 0 #141414; transition: transform .15s, box-shadow .15s; }
    .btn-pop:hover { transform: translateY(-2px); box-shadow: 0 5px 0 #141414; }
    .btn-pop:active { transform: translateY(2px); box-shadow: 0 1px 0 #141414; }
    .wave-top { clip-path: polygon(0 18%, 8% 12%, 20% 6%, 35% 4%, 50% 7%, 62% 11%, 72% 9%, 84% 4%, 93% 6%, 100% 10%, 100% 100%, 0 100%); }
    .wiggle:hover { animation: wiggle .5s ease-in-out; }
    @keyframes wiggle { 25% { transform: rotate(-3deg); } 75% { transform: rotate(3deg); } }
    .reveal-ready [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease; transition-delay: var(--reveal-delay, 0ms); }
    .reveal-ready [data-reveal].is-visible { opacity: 1; transform: none; }
    @media (prefers-reduced-motion: reduce) {
      html { scroll-behavior: auto; }
      .wiggle:hover { animation: none; }
      ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
    }
  </style>
</head>
<body class="bg-blush font-sans text-ink antialiased">
  <% active_page = "index" %>
  <% main_nav = { "about" => "About us", "pastries" => "Pastries", "contact" => "Contact" } %>
  <% more_nav = { "delivery" => "Delivery", "order" => "Build a box" } %>
  <!-- block:start navbar -->
  <header class="relative z-40">
    <nav class="mx-auto flex max-w-6xl items-center justify-between gap-6 px-5 py-5 md:px-8" aria-label="Main">
      <a href="index.html" class="font-display text-3xl leading-none">Crumbelle</a>
      <div class="hidden items-center gap-7 text-sm lg:flex">
        <ul class="flex items-center gap-7">
          <% main_nav.each do |slug, label| %>
            <% active = active_page == slug %>
            <li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="<%= active ? 'font-semibold underline decoration-rose-deep decoration-2 underline-offset-8' : 'hover:text-rose-deep' %>"><%= label %></a></li>
          <% end %>
          <li class="relative" data-dropdown>
            <button type="button" data-dropdown-toggle aria-expanded="false" aria-controls="more-menu" class="flex items-center gap-1.5 <%= 'font-semibold' if more_nav.key?(active_page) %> hover:text-rose-deep">More <i class="fa-solid fa-chevron-down text-[10px]" aria-hidden="true"></i></button>
            <ul id="more-menu" class="absolute right-0 top-full mt-3 hidden w-44 rounded-xl border border-ink bg-white p-2 shadow-[0_4px_0_#141414]">
              <% more_nav.each do |slug, label| %>
                <li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active_page == slug %> class="block rounded-lg px-3 py-2 hover:bg-blush <%= 'bg-blush font-semibold' if active_page == slug %>"><%= label %></a></li>
              <% end %>
            </ul>
          </li>
        </ul>
        <a href="login.html" <%= 'aria-current="page"'.html_safe if active_page == "login" %> class="btn-pop rounded-md border border-ink bg-white px-4 py-1.5">Login</a>
        <a href="order.html" class="btn-pop rounded-md border border-ink bg-rose px-4 py-1.5">Order</a>
      </div>
      <button type="button" data-menu-toggle aria-controls="mobile-menu" aria-expanded="false" aria-label="Open menu" class="btn-pop grid h-11 w-11 place-items-center rounded-md border border-ink bg-white lg:hidden"><i class="fa-solid fa-bars" aria-hidden="true"></i></button>
    </nav>
    <div id="mobile-menu" class="hidden px-5 pb-6 lg:hidden">
      <ul class="grid gap-1 rounded-2xl border border-ink bg-white p-3 text-lg shadow-[0_4px_0_#141414]">
        <% { "index" => "Home" }.merge(main_nav).merge(more_nav).merge("login" => "Login").each do |slug, label| %>
          <% active = active_page == slug %>
          <li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="block rounded-lg px-4 py-2.5 <%= active ? 'bg-rose font-semibold' : 'hover:bg-blush' %>"><%= label %></a></li>
        <% end %>
      </ul>
    </div>
  </header>
  <!-- block:end navbar -->

  <!-- block:start hero -->
  <section class="relative overflow-hidden">
    <div class="checker absolute inset-y-0 right-0 hidden w-[44%] [clip-path:polygon(22%_0,100%_0,100%_100%,0_100%)] lg:block" aria-hidden="true"></div>
    <div class="relative mx-auto grid max-w-6xl items-center gap-12 px-5 pb-20 pt-8 md:px-8 lg:min-h-[36rem] lg:grid-cols-[1.1fr_1fr] lg:pb-24">
      <div>
        <h1 class="font-display text-6xl leading-[0.95] md:text-7xl lg:text-[5.5rem]">Warm <span class="text-rose-deep">pastries</span>,<br><span class="text-rose-deep">quick</span> delivery</h1>
        <p class="mt-6 max-w-md text-[15px] leading-relaxed">Crumbelle bakes the best-loved classics with real ingredients you can trust. Order now and taste what proper baking feels like.</p>
        <div class="mt-8 flex gap-3">
          <a href="order.html" class="btn-pop rounded-md border border-ink bg-rose px-6 py-2.5 font-medium">Order</a>
          <a href="about.html" class="btn-pop rounded-md border border-ink bg-white px-6 py-2.5 font-medium">Learn</a>
        </div>
      </div>
      <div class="relative">
        <div class="checker absolute -inset-4 rounded-3xl lg:hidden" aria-hidden="true"></div>
        <img src="https://images.unsplash.com/photo-1578985545062-69928b1d9587?auto=format&fit=crop&w=1100&q=80" alt="Layered chocolate cake with glossy drip and piped cream rosettes" class="wiggle relative aspect-[5/4] w-full rotate-3 rounded-[2rem] border border-ink object-cover shadow-[0_6px_0_#141414] lg:ml-6">
        <span class="absolute -bottom-5 left-2 -rotate-6 rounded-full border border-ink bg-white px-4 py-2 font-display text-xl shadow-[0_3px_0_#141414] md:left-0">Baked at 5am today</span>
      </div>
    </div>
  </section>
  <!-- block:end hero -->

  <!-- block:start about -->
  <section class="wave-top relative bg-mint pb-24 pt-28 md:pt-36">
    <div class="mx-auto max-w-6xl px-5 md:px-8">
      <div class="mx-auto max-w-2xl text-center" data-reveal>
        <h2 class="font-display text-5xl md:text-6xl">Baked <span class="text-white">properly</span>, every time</h2>
        <p class="mt-5 leading-relaxed">We start with real butter, flour, eggs and time. No shortcuts, no premixes, just the patient craft of real baking. Every pastry tastes like the ones you remember from a grandparent's kitchen.</p>
      </div>
      <div class="mt-14 grid gap-6 md:grid-cols-2">
        <div class="grid gap-6">
          <img src="https://images.unsplash.com/photo-1586985289688-ca3cf47d3e6e?auto=format&fit=crop&w=1000&q=80" alt="Baker piping chocolate rosettes onto a layered cake" class="aspect-[4/3] w-full rounded-xl border border-ink object-cover" loading="lazy" data-reveal>
          <img src="https://images.unsplash.com/photo-1556911073-a517e752729c?auto=format&fit=crop&w=1000&q=80" alt="Baker preparing fresh ingredients in a bright kitchen" class="aspect-[4/3] w-full rounded-xl border border-ink object-cover md:aspect-[4/5]" loading="lazy" data-reveal>
        </div>
        <div class="grid gap-6">
          <img src="https://images.unsplash.com/photo-1486887396153-fa416526c108?auto=format&fit=crop&w=1000&q=80" alt="Hands holding a freshly baked country loaf" class="aspect-[4/3] w-full rounded-xl border border-ink object-cover md:aspect-[4/5]" loading="lazy" data-reveal style="--reveal-delay: 120ms">
          <img src="https://images.unsplash.com/photo-1534432182912-63863115e106?auto=format&fit=crop&w=1000&q=80" alt="Trays of pastries and cakes laid out on the counter" class="aspect-[4/3] w-full rounded-xl border border-ink object-cover" loading="lazy" data-reveal style="--reveal-delay: 120ms">
        </div>
      </div>
    </div>
  </section>
  <!-- block:end about -->

  <% products = [
    ["Butter croissant", "Box of 6", "$18", "1555507036-ab1f4038808a", "Two golden croissants dusted with sugar"],
    ["Fudge brownie", "Box of 9", "$16", "1606313564200-e75d5e30476c", "Stack of fudgy chocolate brownies"],
    ["Cinnamon roll", "Box of 6", "$20", "1509365465985-25d11c17e812", "Cinnamon rolls dusted with sugar on a dark tray"],
    ["Lemon meringue tart", "Whole tart", "$24", "1519915028121-7d3463d20b13", "Lemon tart topped with toasted meringue"],
    ["Cherry lattice pie", "Two mini pies", "$15", "1464305795204-6f5bbfc7fb81", "Two cherry lattice pies with fresh berries"],
    ["Confetti cupcakes", "Box of 4", "$17", "1519869325930-281384150729", "Vanilla cupcakes with swirled frosting and sprinkles"]
  ] %>
  <!-- block:start products -->
  <section class="bg-blush">
    <div class="mx-auto max-w-6xl px-5 py-20 md:px-8 md:py-24">
      <div class="flex flex-wrap items-end justify-between gap-6">
        <div class="max-w-xl">
          <h2 class="font-display text-5xl md:text-6xl">Crowd <span class="text-rose-deep">favourites</span></h2>
          <p class="mt-4 leading-relaxed">The bakes that keep our regulars coming back, made fresh each day and ready when you are.</p>
        </div>
        <a href="pastries.html" class="btn-pop rounded-md border border-ink bg-white px-5 py-2 text-sm font-medium">Browse</a>
      </div>
      <ul class="mt-12 grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
        <% products.each_with_index do |(name, size, price, photo, alt), index| %>
          <li data-reveal style="--reveal-delay: <%= (index % 3) * 100 %>ms">
            <a href="pastries.html" class="group block">
              <span class="block overflow-hidden rounded-xl border border-ink"><img src="https://images.unsplash.com/photo-<%= photo %>?auto=format&fit=crop&w=800&q=80" alt="<%= alt %>" class="aspect-square w-full object-cover transition duration-500 group-hover:scale-105" loading="lazy"></span>
              <span class="mt-3 block rounded-xl border border-ink bg-rose px-4 py-3 transition group-hover:-translate-y-1">
                <span class="block font-medium"><%= name %></span>
                <span class="block text-xs"><%= size %></span>
                <span class="mt-2 block text-xl font-semibold"><%= price %></span>
              </span>
            </a>
          </li>
        <% end %>
      </ul>
    </div>
  </section>
  <!-- block:end products -->

  <!-- block:start process -->
  <section class="bg-blush pb-24">
    <div class="mx-auto max-w-6xl px-5 md:px-8">
      <h2 class="text-center font-display text-4xl md:text-5xl">Oven to doorstep in three steps</h2>
      <ol class="mt-12 grid border border-ink md:grid-cols-3">
        <% [["fa-fire-burner", "Bake", "Every pastry leaves the oven golden and still warm.", "bg-rose"], ["fa-box-open", "Pack", "We box them gently so nothing arrives squashed.", "bg-mint"], ["fa-truck-fast", "Ship", "Your treats turn up quickly, fresh and ready to enjoy.", "bg-pistachio"]].each_with_index do |(icon, title, text, tone), index| %>
          <li class="<%= tone %> px-6 py-8 text-center <%= 'border-t border-ink md:border-l md:border-t-0' unless index.zero? %>">
            <span class="mx-auto grid h-16 w-16 place-items-center rounded-full bg-white text-xl" aria-hidden="true"><i class="fa-solid <%= icon %>"></i></span>
            <h3 class="mt-4 font-display text-3xl"><%= title %></h3>
            <p class="mx-auto mt-3 max-w-[16rem] text-sm leading-relaxed"><%= text %></p>
          </li>
        <% end %>
      </ol>
    </div>
  </section>
  <!-- block:end process -->

  <% promises = [["fa-egg", "Butter, flour, eggs. That's the list", "Plus salt and patience. Nothing else goes in."], ["fa-rotate-left", "Fresh, or your money back", "If it isn't perfect when it lands, we refund you. No questions."], ["fa-truck", "Baked today, sent today", "Out of the oven at dawn and on its way by lunch."], ["fa-ban", "No mystery ingredients", "No preservatives, no fillers, just good baking done right."]] %>
  <!-- block:start features -->
  <section class="checker">
    <div class="mx-auto max-w-6xl px-5 py-20 md:px-8 md:py-24">
      <div class="mx-auto max-w-2xl text-center">
        <h2 class="font-display text-5xl md:text-6xl">What goes in is what you taste</h2>
        <p class="mt-5 leading-relaxed">We bake in the open. Every ingredient is one you'd keep in your own cupboard, and we're happy to tell you exactly what they are.</p>
      </div>
      <div class="mt-14 grid items-center gap-6 lg:grid-cols-[1fr_1.3fr_1fr]">
        <% left, right = promises.each_slice(2).to_a %>
        <% [left, nil, right].each do |group| %>
          <% if group %>
            <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-1">
              <% group.each do |icon, title, text| %>
                <div class="rounded-2xl border border-ink bg-white/70 p-6 text-center backdrop-blur" data-reveal>
                  <span class="mx-auto grid h-14 w-14 place-items-center rounded-full border border-ink text-lg" aria-hidden="true"><i class="fa-solid <%= icon %>"></i></span>
                  <h3 class="mt-4 font-display text-2xl leading-tight"><%= title %></h3>
                  <p class="mt-2 text-sm leading-relaxed"><%= text %></p>
                </div>
              <% end %>
            </div>
          <% else %>
            <div class="relative mx-auto w-full max-w-sm">
              <img src="https://images.unsplash.com/photo-1621303837174-89787a7d4729?auto=format&fit=crop&w=900&q=80" alt="Pink drip cake topped with an ice cream cone on a white cake stand" class="aspect-square w-full rounded-full border border-ink object-cover shadow-[0_6px_0_#141414]" loading="lazy">
              <span class="absolute -right-2 top-6 rotate-12 rounded-full border border-ink bg-rose px-4 py-2 font-display text-xl">100% real</span>
            </div>
          <% end %>
        <% end %>
      </div>
    </div>
  </section>
  <!-- block:end features -->

  <% quotes = [["They taste like they came from the corner bakery, not a delivery box.", "Sofia Lindqvist", "Regular customer", 2], ["Quick delivery, and the croissants were still warm when the box opened.", "Daniel Mensah", "Breakfast lover", 3], ["Finally a bakery I can trust. Short ingredient lists, brilliant baking.", "Aiko Tanaka", "Home baker", 4]] %>
  <!-- block:start reviews -->
  <section class="bg-blush">
    <div class="mx-auto max-w-6xl px-5 py-20 md:px-8 md:py-24">
      <h2 class="font-display text-5xl md:text-6xl">Kind <span class="text-rose-deep">words</span></h2>
      <p class="mt-3">Real people, real breakfasts with Crumbelle.</p>
      <div class="mt-12 grid gap-10 md:grid-cols-3">
        <% quotes.each_with_index do |(quote, name, role, avatar), index| %>
          <figure data-reveal style="--reveal-delay: <%= index * 120 %>ms">
            <p class="text-mint" aria-label="Five stars"><% 5.times do %><i class="fa-solid fa-star" aria-hidden="true"></i><% end %></p>
            <blockquote class="mt-4 font-display text-2xl leading-snug">&ldquo;<%= quote %>&rdquo;</blockquote>
            <figcaption class="mt-5 flex items-center gap-3">
              <img src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-<%= avatar %>.jpg" alt="Portrait of <%= name %>" class="h-12 w-12 rounded-full object-cover" loading="lazy">
              <span><span class="block text-sm font-semibold"><%= name %></span><span class="text-sm"><%= role %></span></span>
            </figcaption>
          </figure>
        <% end %>
      </div>
    </div>
  </section>
  <!-- block:end reviews -->

  <section class="wave-top bg-white pb-20 pt-28 md:pb-24">
    <div class="mx-auto max-w-6xl px-5 md:px-8">
      <h2 class="font-display text-5xl md:text-6xl">Made for the <span class="text-rose-deep">way you live</span></h2>
      <p class="mt-4 max-w-xl leading-relaxed">You're busy. So we ship quickly and pack cleverly, and fresh baking fits into your week without the fuss.</p>
      <div class="mt-12 grid gap-6 md:grid-cols-3">
        <% [["Two-day delivery almost everywhere", "Order in the morning, enjoy fresh pastries by the next afternoon.", "1526367790999-0150786686a2", "Courier cycling a delivery bag down a narrow street", "bg-pistachio", "delivery"], ["Packaging that's kind to the planet", "Our boxes are fully compostable, because good baking shouldn't cost the earth.", "1530610476181-d83430b64dcd", "Fresh croissants piled on a café counter", "bg-mint", "about"], ["Subscribe and save on every box", "A fresh box every week at a price that actually makes sense.", "1556910103-1c02745aae4d", "Couple cooking together in a home kitchen", "bg-peach", "order"]].each do |title, text, photo, alt, tone, href| %>
          <a href="<%= href %>.html" class="group flex flex-col overflow-hidden rounded-2xl border border-ink <%= tone %> transition hover:-translate-y-1 hover:shadow-[0_6px_0_#141414]" data-reveal>
            <img src="https://images.unsplash.com/photo-<%= photo %>?auto=format&fit=crop&w=800&q=80" alt="<%= alt %>" class="aspect-[16/10] w-full object-cover" loading="lazy">
            <span class="flex-1 p-7">
              <span class="block font-display text-3xl leading-tight"><%= title %></span>
              <span class="mt-4 block text-sm leading-relaxed"><%= text %></span>
            </span>
          </a>
        <% end %>
      </div>
    </div>
  </section>

  <% faqs = [["How fresh is everything?", "Everything is baked the morning it ships. Nothing is made days ahead, so you get it at its best, usually within 24 hours of baking."], ["How long does delivery take?", "Most orders arrive in two to three working days in insulated packaging, and every order comes with tracking."], ["Do you bake gluten-free?", "Not yet, though we're testing recipes. For now everything contains wheat flour, and we're careful about cross-contamination."], ["What if my box arrives damaged?", "Tell us within 24 hours and we'll replace it or refund you. We pack with care, and we stand behind every box."], ["Can I pause or cancel a subscription?", "Any time, with no penalty. Pause or cancel from your account page whenever you like."]] %>
  <!-- block:start faq -->
  <section class="bg-white">
    <div class="mx-auto max-w-3xl px-5 pb-20 md:px-8 md:pb-24">
      <div class="text-center">
        <h2 class="font-display text-6xl text-rose-deep">Questions</h2>
        <p class="mt-3">Answers about freshness, delivery and what we bake.</p>
      </div>
      <div class="mt-10 border-t border-ink/15" data-accordion>
        <% faqs.each_with_index do |(question, answer), index| %>
          <div class="border-b border-ink/15">
            <h3>
              <button type="button" data-accordion-trigger aria-expanded="<%= index.zero? %>" aria-controls="faq-<%= index %>" class="flex w-full items-center justify-between gap-6 py-5 text-left font-semibold">
                <%= question %>
                <i class="fa-solid fa-chevron-down shrink-0 text-xs transition-transform" aria-hidden="true"></i>
              </button>
            </h3>
            <div id="faq-<%= index %>" <%= 'hidden' unless index.zero? %> class="pb-5 leading-relaxed"><%= answer %></div>
          </div>
        <% end %>
      </div>
      <div class="mt-16 text-center">
        <h3 class="font-display text-4xl">Still wondering about something?</h3>
        <p class="mx-auto mt-3 max-w-sm">We're happy to talk about what we bake and how it reaches you.</p>
        <a href="contact.html" class="btn-pop mt-6 inline-block rounded-md border border-ink bg-white px-6 py-2.5 font-medium">Contact</a>
      </div>
    </div>
  </section>
  <!-- block:end faq -->

  <!-- block:start cta -->
  <section class="grid md:grid-cols-2">
    <div class="checker flex flex-col justify-center px-5 py-16 md:px-12 lg:px-[max(3rem,calc((100vw-72rem)/2+2rem))]">
      <h2 class="font-display text-5xl leading-tight md:text-6xl">Hungry for something fresh?</h2>
      <p class="mt-5 max-w-md text-lg">Order today and taste the difference real baking makes.</p>
      <div class="mt-8 flex gap-3">
        <a href="order.html" class="btn-pop rounded-md border border-ink bg-rose px-6 py-2.5 font-medium">Order</a>
        <a href="pastries.html" class="btn-pop rounded-md border border-ink bg-white px-6 py-2.5 font-medium">Learn</a>
      </div>
    </div>
    <img src="https://images.unsplash.com/photo-1495147466023-ac5c588e2e94?auto=format&fit=crop&w=1200&q=80" alt="Rows of small fruit tarts topped with berries and kiwi" class="aspect-[4/3] h-full w-full object-cover md:aspect-auto" loading="lazy">
  </section>
  <!-- block:end cta -->

  <!-- block:start footer -->
  <footer class="bg-mint">
    <div class="mx-auto max-w-6xl px-5 py-16 md:px-8">
      <div class="grid gap-10 rounded-2xl border border-ink bg-rose p-8 md:grid-cols-[1.4fr_1fr_1fr] md:p-12">
        <div>
          <a href="index.html" class="font-display text-4xl">Crumbelle</a>
          <p class="mt-6 text-sm font-semibold">Location</p>
          <p class="text-sm">14 Mill Lane, Bath BA1 2JX</p>
          <p class="mt-4 text-sm font-semibold">Reach us</p>
          <p class="text-sm"><a href="tel:+441225000418" class="underline">01225 000 418</a><br><a href="mailto:hello@crumbelle.co" class="underline">hello@crumbelle.co</a></p>
          <ul class="mt-6 flex gap-4 text-lg">
            <% [["fa-facebook", "Facebook", "https://www.facebook.com"], ["fa-instagram", "Instagram", "https://www.instagram.com"], ["fa-tiktok", "TikTok", "https://www.tiktok.com"], ["fa-youtube", "YouTube", "https://www.youtube.com"]].each do |icon, label, url| %>
              <li><a href="<%= url %>" aria-label="<%= label %>" class="transition hover:text-white"><i class="fa-brands <%= icon %>" aria-hidden="true"></i></a></li>
            <% end %>
          </ul>
        </div>
        <ul class="grid content-start gap-3 text-sm font-semibold">
          <% [["about", "Our story"], ["about", "The craft"], ["about", "Quality promise"], ["about", "Meet the team"], ["order", "Ordering"]].each do |slug, label| %><li><a href="<%= slug %>.html" class="hover:underline"><%= label %></a></li><% end %>
        </ul>
        <ul class="grid content-start gap-3 text-sm font-semibold">
          <% [["pastries", "Menu"], ["delivery", "Delivery"], ["delivery", "Track an order"], ["contact", "Support"], ["login", "Your account"]].each do |slug, label| %><li><a href="<%= slug %>.html" class="hover:underline"><%= label %></a></li><% end %>
        </ul>
      </div>
      <div class="mt-8 flex flex-wrap items-center justify-between gap-4 text-sm">
        <p>&copy; <span data-current-year>2026</span> Crumbelle Bakery</p>
        <ul class="flex flex-wrap gap-6 underline">
          <li><a href="contact.html">Terms of service</a></li>
          <li><a href="contact.html">Cookie settings</a></li>
          <li><a href="contact.html">Privacy policy</a></li>
        </ul>
      </div>
    </div>
  </footer>
  <!-- block:end footer -->

  <script>
    document.querySelectorAll('[data-menu-toggle]').forEach((button) => {
      const menu = document.getElementById(button.getAttribute('aria-controls'));
      if (!menu) return;
      button.addEventListener('click', () => {
        const open = button.getAttribute('aria-expanded') === 'true';
        button.setAttribute('aria-expanded', String(!open));
        menu.classList.toggle('hidden', open);
      });
    });

    document.querySelectorAll('[data-dropdown]').forEach((dropdown) => {
      const toggle = dropdown.querySelector('[data-dropdown-toggle]');
      const menu = document.getElementById(toggle.getAttribute('aria-controls'));
      const set = (open) => { toggle.setAttribute('aria-expanded', String(open)); menu.classList.toggle('hidden', !open); };
      toggle.addEventListener('click', () => set(toggle.getAttribute('aria-expanded') !== 'true'));
      document.addEventListener('click', (event) => { if (!dropdown.contains(event.target)) set(false); });
      dropdown.addEventListener('keydown', (event) => { if (event.key === 'Escape') { set(false); toggle.focus(); } });
    });

    document.querySelectorAll('[data-accordion]').forEach((accordion) => {
      accordion.querySelectorAll('[data-accordion-trigger]').forEach((trigger) => {
        const panel = document.getElementById(trigger.getAttribute('aria-controls'));
        const icon = () => trigger.querySelector('svg') || trigger.querySelector('i');
        const sync = () => { const open = trigger.getAttribute('aria-expanded') === 'true'; panel.hidden = !open; icon()?.classList.toggle('rotate-180', open); };
        trigger.addEventListener('click', () => { trigger.setAttribute('aria-expanded', String(trigger.getAttribute('aria-expanded') !== 'true')); sync(); });
        sync();
      });
    });

    document.querySelectorAll('[data-tabs]').forEach((tablist) => {
      const tabs = [...tablist.querySelectorAll('[role="tab"]')];
      const select = (tab) => tabs.forEach((other) => {
        const active = other === tab;
        other.setAttribute('aria-selected', String(active));
        other.tabIndex = active ? 0 : -1;
        document.getElementById(other.getAttribute('aria-controls')).hidden = !active;
      });
      tabs.forEach((tab, index) => {
        tab.addEventListener('click', () => select(tab));
        tab.addEventListener('keydown', (event) => {
          const step = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[event.key];
          if (!step) return;
          event.preventDefault();
          const next = tabs[(index + step + tabs.length) % tabs.length];
          next.focus();
          select(next);
        });
      });
    });

    document.querySelectorAll('[data-box-builder]').forEach((builder) => {
      const size = Number(builder.dataset.boxSize);
      const summary = builder.querySelector('[data-box-summary]');
      const count = builder.querySelector('[data-box-count]');
      const total = builder.querySelector('[data-box-total]');
      const bar = builder.querySelector('[data-box-bar]');
      const submit = builder.querySelector('[data-box-submit]');
      const slots = [...builder.querySelectorAll('[data-box-slot]')];
      const update = () => {
        const items = [...builder.querySelectorAll('[data-box-item]')];
        let pieces = 0;
        let price = 0;
        const fill = [];
        items.forEach((item) => {
          const qty = Number(item.querySelector('[data-qty]').textContent);
          pieces += qty;
          price += qty * Number(item.dataset.price);
          for (let i = 0; i < qty; i += 1) fill.push(item.dataset.emoji);
          item.querySelector('[data-step="-1"]').disabled = qty === 0;
        });
        items.forEach((item) => { item.querySelector('[data-step="1"]').disabled = pieces >= size; });
        slots.forEach((slot, i) => { slot.textContent = fill[i] || ''; slot.classList.toggle('is-filled', Boolean(fill[i])); });
        count.textContent = pieces;
        total.textContent = price.toFixed(2);
        bar.style.width = `${(pieces / size) * 100}%`;
        summary.textContent = pieces === size ? 'Your box is full. Ready when you are!' : `Add ${size - pieces} more to fill your box.`;
        submit.disabled = pieces !== size;
      };
      builder.addEventListener('click', (event) => {
        const button = event.target.closest('[data-step]');
        if (!button) return;
        const qty = button.closest('[data-box-item]').querySelector('[data-qty]');
        qty.textContent = Math.max(0, Number(qty.textContent) + Number(button.dataset.step));
        update();
      });
      builder.addEventListener('submit', (event) => {
        event.preventDefault();
        builder.querySelector('[data-form-status]').textContent = 'Lovely! Your box is saved. Pick a delivery day at checkout.';
      });
      update();
    });

    document.querySelectorAll('[data-postcode-check]').forEach((form) => {
      const status = form.querySelector('[data-form-status]');
      form.addEventListener('submit', (event) => {
        event.preventDefault();
        const value = String(form.querySelector('[name="postcode"]').value || '').trim().toUpperCase();
        if (!value) { status.textContent = 'Type your postcode first.'; return; }
        const area = value.replace(/[^A-Z]/g, '').slice(0, 2);
        const local = ['BA', 'BS', 'SN', 'GL'].includes(area);
        status.textContent = local ? `Good news: we deliver to ${value} the next day, Tuesday to Saturday.` : `We deliver to ${value} in two to three working days.`;
      });
    });

    document.querySelectorAll('[data-flip]').forEach((card) => {
      card.addEventListener('click', () => card.setAttribute('aria-pressed', String(card.getAttribute('aria-pressed') !== 'true')));
    });

    document.querySelectorAll('[data-contact-form]').forEach((form) => {
      form.addEventListener('submit', (event) => {
        event.preventDefault();
        const status = form.querySelector('[data-form-status]');
        if (!form.checkValidity()) {
          status.textContent = form.dataset.error;
          form.querySelector(':invalid')?.focus();
          return;
        }
        status.textContent = form.dataset.success;
        form.reset();
      });
    });

    document.querySelectorAll('[data-current-year]').forEach((el) => { el.textContent = new Date().getFullYear(); });

    (() => {
      const items = document.querySelectorAll('[data-reveal]');
      const skip = navigator.webdriver || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches;
      if (!items.length || skip) return;
      document.documentElement.classList.add('reveal-ready');
      const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          entry.target.classList.add('is-visible');
          observer.unobserve(entry.target);
        });
      }, { rootMargin: '0px 0px -10% 0px' });
      items.forEach((item) => observer.observe(item));
    })();
  </script>
</body>
</html>

Unlimited access to all templates

Unlock our entire library of premium UI kits, dashboards, and landing pages. Renews automatically, cancel anytime.

$20 / 3 months or $60 / year
Get Unlimited Access

More Food & Restaurant Templates