Cookbook — Recipe Collection / Cookbook index
An editorial cookbook index page that gathers fictional recipes into a book-like collection. A gradient cover with curator, recipe count and total time sits above chapter sections for Starters, Mains and Desserts, each holding appetizing CSS-gradient recipe cards with times, difficulty and servings. Sticky chapter jump-nav, a save-collection toggle, and a grid or list view switch make it feel like browsing a real seasonal cookbook, all in warm cream tones.
MCP
Code
:root {
--cream: #faf6ef;
--paper: #fffdf8;
--ink: #2b2622;
--ink-2: #5c534a;
--muted: #8a7f73;
--tomato: #d6452b;
--tomato-d: #b8351e;
--saffron: #e8a33d;
--sage: #7c8a6b;
--clay: #c8775a;
--line: rgba(43, 38, 34, 0.12);
--line-2: rgba(43, 38, 34, 0.2);
--ok: #3f8f5f;
--warn: #d98a2b;
--danger: #c8412b;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 22px;
--sh-1: 0 1px 2px rgba(43, 38, 34, 0.1);
--sh-2: 0 10px 30px rgba(43, 38, 34, 0.1);
--serif: "Fraunces", Georgia, serif;
--sans: "Inter", system-ui, -apple-system, sans-serif;
}
* {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
scroll-padding-top: 84px;
}
body {
margin: 0;
font-family: var(--sans);
line-height: 1.6;
color: var(--ink);
background: var(--cream);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.skip-link {
position: absolute;
left: -999px;
top: 0;
z-index: 50;
background: var(--ink);
color: var(--paper);
padding: 10px 16px;
border-radius: 0 0 var(--r-sm) 0;
}
.skip-link:focus {
left: 0;
}
:focus-visible {
outline: 3px solid var(--saffron);
outline-offset: 2px;
border-radius: var(--r-sm);
}
/* ---------- Cover ---------- */
.cover {
display: grid;
grid-template-columns: 1.05fr 1fr;
gap: 0;
max-width: 1120px;
margin: 28px auto 0;
padding: 0 24px;
}
.cover__art {
position: relative;
border-radius: var(--r-lg);
min-height: 380px;
overflow: hidden;
background:
radial-gradient(120% 90% at 20% 15%, #fff3e0 0%, transparent 55%),
linear-gradient(150deg, #f3d9b0, #e7b07a 55%, #d68a5e);
box-shadow: var(--sh-2);
margin-right: 28px;
display: grid;
place-items: center;
}
.blob {
position: absolute;
border-radius: 50%;
filter: blur(6px);
opacity: 0.92;
mix-blend-mode: multiply;
}
.blob--tomato {
width: 200px;
height: 200px;
top: -30px;
left: -20px;
background: radial-gradient(circle at 35% 30%, #ef6a4e, var(--tomato-d));
}
.blob--saffron {
width: 170px;
height: 170px;
bottom: -30px;
right: 30px;
background: radial-gradient(circle at 35% 30%, #f5c074, var(--saffron));
}
.blob--sage {
width: 150px;
height: 150px;
bottom: 40px;
left: 30px;
background: radial-gradient(circle at 35% 30%, #97a583, var(--sage));
}
.cover__emoji {
position: relative;
font-size: 56px;
letter-spacing: 8px;
filter: drop-shadow(0 6px 12px rgba(43, 38, 34, 0.25));
}
.cover__body {
padding: 8px 0 8px;
align-self: center;
}
.kicker {
font-family: var(--sans);
text-transform: uppercase;
letter-spacing: 0.18em;
font-size: 12px;
font-weight: 600;
color: var(--tomato);
margin: 0 0 10px;
}
.cover__title {
font-family: var(--serif);
font-weight: 600;
font-size: clamp(2.1rem, 5vw, 3.2rem);
line-height: 1.05;
margin: 0 0 14px;
letter-spacing: -0.01em;
}
.cover__lede {
color: var(--ink-2);
max-width: 46ch;
margin: 0 0 20px;
font-size: 1.02rem;
}
.curator {
display: flex;
align-items: center;
gap: 12px;
margin: 0 0 22px;
}
.curator__avatar {
width: 44px;
height: 44px;
border-radius: 50%;
display: grid;
place-items: center;
font-size: 22px;
background: var(--paper);
border: 1px solid var(--line);
box-shadow: var(--sh-1);
}
.curator__meta {
display: flex;
flex-direction: column;
line-height: 1.3;
}
.curator__label {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.curator__name {
font-family: var(--serif);
font-weight: 600;
font-size: 1.05rem;
}
.cover__stats {
display: flex;
gap: 14px;
list-style: none;
padding: 0;
margin: 0 0 24px;
flex-wrap: wrap;
}
.cover__stats li {
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 10px 16px;
display: flex;
flex-direction: column;
min-width: 92px;
box-shadow: var(--sh-1);
}
.cover__stats strong {
font-family: var(--serif);
font-size: 1.35rem;
font-weight: 600;
}
.cover__stats span {
font-size: 12px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.1em;
}
.cover__actions {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
/* ---------- Buttons ---------- */
.btn {
font-family: var(--sans);
font-size: 0.95rem;
font-weight: 600;
border-radius: 999px;
padding: 12px 22px;
border: 1px solid transparent;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
text-decoration: none;
transition: transform 0.12s ease, background 0.2s ease, box-shadow 0.2s ease;
}
.btn:active {
transform: translateY(1px);
}
.btn--save {
background: var(--tomato);
color: #fff;
box-shadow: var(--sh-1);
}
.btn--save:hover {
background: var(--tomato-d);
}
.btn--save.is-saved {
background: var(--sage);
}
.btn--ghost {
background: var(--paper);
border-color: var(--line-2);
color: var(--ink);
}
.btn--ghost:hover {
background: #f4ede1;
}
/* ---------- Chapter nav ---------- */
.chapnav {
position: sticky;
top: 0;
z-index: 20;
background: rgba(250, 246, 239, 0.9);
backdrop-filter: blur(8px);
border-bottom: 1px solid var(--line);
margin-top: 36px;
padding: 10px 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
}
.chapnav__list {
display: flex;
gap: 6px;
list-style: none;
margin: 0;
padding: 0;
flex-wrap: wrap;
}
.chapnav__link {
font-weight: 600;
font-size: 0.92rem;
color: var(--ink-2);
text-decoration: none;
padding: 8px 14px;
border-radius: 999px;
transition: background 0.2s ease, color 0.2s ease;
}
.chapnav__link:hover {
background: #f1e7d8;
}
.chapnav__link.is-active {
background: var(--ink);
color: var(--paper);
}
.viewtoggle {
display: inline-flex;
border: 1px solid var(--line-2);
border-radius: 999px;
background: var(--paper);
padding: 3px;
}
.viewtoggle__btn {
border: 0;
background: transparent;
font-family: var(--sans);
font-weight: 600;
font-size: 0.85rem;
color: var(--ink-2);
padding: 7px 14px;
border-radius: 999px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
}
.viewtoggle__btn.is-active {
background: var(--saffron);
color: var(--ink);
}
/* ---------- Book / chapters ---------- */
.book {
max-width: 1120px;
margin: 0 auto;
padding: 40px 24px 24px;
}
.chapter {
margin-bottom: 56px;
}
.chapter__head {
display: flex;
align-items: center;
gap: 18px;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 2px solid var(--line);
}
.chapter__num {
font-family: var(--serif);
font-weight: 700;
font-size: 2rem;
color: var(--paper);
background: linear-gradient(150deg, var(--tomato), var(--clay));
width: 58px;
height: 58px;
border-radius: var(--r-md);
display: grid;
place-items: center;
flex: none;
box-shadow: var(--sh-1);
}
.chapter__title {
font-family: var(--serif);
font-weight: 600;
font-size: 1.9rem;
margin: 0;
}
.chapter__sub {
margin: 2px 0 0;
color: var(--muted);
font-style: italic;
}
/* ---------- Cards ---------- */
.cards {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 22px;
counter-reset: none;
}
.card {
position: relative;
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-lg);
overflow: hidden;
box-shadow: var(--sh-1);
transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
cursor: pointer;
}
.card:hover,
.card:focus-visible {
transform: translateY(-4px);
box-shadow: var(--sh-2);
border-color: var(--line-2);
}
.card__index {
position: absolute;
top: 12px;
left: 12px;
z-index: 2;
font-family: var(--serif);
font-weight: 700;
font-size: 0.95rem;
color: var(--ink);
background: rgba(255, 253, 248, 0.92);
border-radius: 999px;
width: 34px;
height: 34px;
display: grid;
place-items: center;
box-shadow: var(--sh-1);
}
.card__photo {
height: 150px;
display: grid;
place-items: center;
font-size: 44px;
position: relative;
}
.card__photo span {
filter: drop-shadow(0 4px 8px rgba(43, 38, 34, 0.22));
}
.card__photo--tomato {
background:
radial-gradient(90% 80% at 70% 20%, #ffe2d2 0%, transparent 60%),
linear-gradient(150deg, #ef6a4e, var(--tomato-d));
}
.card__photo--saffron {
background:
radial-gradient(90% 80% at 70% 20%, #fff0d6 0%, transparent 60%),
linear-gradient(150deg, #f5c074, var(--saffron));
}
.card__photo--sage {
background:
radial-gradient(90% 80% at 70% 20%, #e9efdf 0%, transparent 60%),
linear-gradient(150deg, #9aa985, var(--sage));
}
.card__photo--clay {
background:
radial-gradient(90% 80% at 70% 20%, #f6ddcf 0%, transparent 60%),
linear-gradient(150deg, #dd9474, var(--clay));
}
.card__body {
padding: 16px 18px 20px;
}
.card__title {
font-family: var(--serif);
font-weight: 600;
font-size: 1.18rem;
line-height: 1.2;
margin: 0 0 8px;
}
.card__desc {
color: var(--ink-2);
font-size: 0.92rem;
margin: 0 0 14px;
}
.card__meta {
display: flex;
flex-wrap: wrap;
gap: 6px 14px;
list-style: none;
margin: 0;
padding: 0;
font-size: 0.82rem;
color: var(--muted);
font-weight: 500;
}
/* ---------- List view ---------- */
.book[data-view="list"] .cards {
grid-template-columns: 1fr;
gap: 12px;
}
.book[data-view="list"] .card {
display: grid;
grid-template-columns: 120px 1fr;
align-items: stretch;
}
.book[data-view="list"] .card__photo {
height: 100%;
min-height: 110px;
font-size: 34px;
}
.book[data-view="list"] .card__index {
top: 10px;
left: 10px;
}
.book[data-view="list"] .card__desc {
max-width: 70ch;
}
/* ---------- Footer ---------- */
.footer {
max-width: 1120px;
margin: 0 auto;
padding: 28px 24px 56px;
border-top: 1px solid var(--line);
color: var(--muted);
text-align: center;
font-size: 0.9rem;
}
.footer p {
margin: 4px 0;
}
.footer__fine {
font-size: 0.8rem;
font-style: italic;
}
/* ---------- Toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 28px;
transform: translateX(-50%) translateY(20px);
background: var(--ink);
color: var(--paper);
padding: 12px 20px;
border-radius: 999px;
font-size: 0.9rem;
font-weight: 500;
box-shadow: var(--sh-2);
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease, transform 0.25s ease;
z-index: 60;
}
.toast.is-visible {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
/* ---------- Responsive ---------- */
@media (max-width: 920px) {
.cover {
grid-template-columns: 1fr;
gap: 24px;
}
.cover__art {
margin-right: 0;
min-height: 240px;
}
.cards {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 720px) {
.cards {
grid-template-columns: 1fr;
}
.book[data-view="list"] .card {
grid-template-columns: 90px 1fr;
}
}
@media (max-width: 480px) {
.chapnav {
justify-content: center;
}
.chapter__head {
gap: 12px;
}
.chapter__num {
width: 48px;
height: 48px;
font-size: 1.6rem;
}
}
@media (prefers-reduced-motion: reduce) {
* {
scroll-behavior: auto !important;
transition: none !important;
}
}
@media print {
.chapnav,
.cover__actions,
.toast,
.skip-link {
display: none !important;
}
body {
background: #fff;
}
.card {
break-inside: avoid;
box-shadow: none;
}
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-visible");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-visible");
}, 2400);
}
/* ---------- Save collection toggle ---------- */
var saveBtn = document.getElementById("saveBtn");
if (saveBtn) {
var labelEl = saveBtn.querySelector(".btn__label");
var iconEl = saveBtn.querySelector(".btn__icon");
saveBtn.addEventListener("click", function () {
var saved = saveBtn.classList.toggle("is-saved");
saveBtn.setAttribute("aria-pressed", saved ? "true" : "false");
if (labelEl) labelEl.textContent = saved ? "Saved" : "Save collection";
if (iconEl) iconEl.textContent = saved ? "✅" : "🔖";
toast(saved ? "Added to your cookbook shelf" : "Removed from your shelf");
});
}
/* ---------- Grid / List view switch ---------- */
var book = document.querySelector(".book");
var viewGrid = document.getElementById("viewGrid");
var viewList = document.getElementById("viewList");
function setView(view) {
if (!book) return;
book.setAttribute("data-view", view);
var gridActive = view === "grid";
viewGrid.classList.toggle("is-active", gridActive);
viewList.classList.toggle("is-active", !gridActive);
viewGrid.setAttribute("aria-pressed", gridActive ? "true" : "false");
viewList.setAttribute("aria-pressed", !gridActive ? "true" : "false");
}
if (viewGrid && viewList) {
viewGrid.addEventListener("click", function () {
setView("grid");
});
viewList.addEventListener("click", function () {
setView("list");
});
}
/* ---------- Chapter jump-nav + scrollspy ---------- */
var links = Array.prototype.slice.call(
document.querySelectorAll(".chapnav__link")
);
var sections = links
.map(function (l) {
return document.querySelector(l.getAttribute("href"));
})
.filter(Boolean);
function setActive(id) {
links.forEach(function (l) {
l.classList.toggle("is-active", l.getAttribute("href") === "#" + id);
});
}
if ("IntersectionObserver" in window && sections.length) {
var observer = new IntersectionObserver(
function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) setActive(e.target.id);
});
},
{ rootMargin: "-45% 0px -50% 0px", threshold: 0 }
);
sections.forEach(function (s) {
observer.observe(s);
});
}
/* Smooth-scroll active state on click (immediate feedback) */
links.forEach(function (l) {
l.addEventListener("click", function () {
setActive(l.getAttribute("href").slice(1));
});
});
/* ---------- Card "open recipe" affordance ---------- */
var cards = document.querySelectorAll(".card");
cards.forEach(function (card) {
function open() {
var title = card.querySelector(".card__title");
toast("Opening “" + (title ? title.textContent : "recipe") + "”…");
}
card.addEventListener("click", open);
card.addEventListener("keydown", function (ev) {
if (ev.key === "Enter" || ev.key === " ") {
ev.preventDefault();
open();
}
});
});
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>The Slow Sunday Kitchen — A Recipe Collection</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip-link" href="#chapters">Skip to recipes</a>
<header class="cover" role="banner">
<div class="cover__art" aria-hidden="true">
<span class="blob blob--tomato"></span>
<span class="blob blob--saffron"></span>
<span class="blob blob--sage"></span>
<span class="cover__emoji">🍅🌿🍋</span>
</div>
<div class="cover__body">
<p class="kicker">Curated collection · Seasonal</p>
<h1 class="cover__title">The Slow Sunday Kitchen</h1>
<p class="cover__lede">
Eighteen unhurried recipes for the days when the oven does the work and
the kitchen smells like home — from bright little starters to a custard
worth waiting for.
</p>
<div class="curator">
<span class="curator__avatar" aria-hidden="true">👩🍳</span>
<span class="curator__meta">
<span class="curator__label">Curated by</span>
<span class="curator__name">Marisol Vega</span>
</span>
</div>
<ul class="cover__stats" aria-label="Collection summary">
<li><strong id="stat-count">9</strong><span>recipes</span></li>
<li><strong id="stat-time">11h 25m</strong><span>total time</span></li>
<li><strong>3</strong><span>chapters</span></li>
</ul>
<div class="cover__actions">
<button class="btn btn--save" id="saveBtn" aria-pressed="false">
<span class="btn__icon" aria-hidden="true">🔖</span>
<span class="btn__label">Save collection</span>
</button>
<a class="btn btn--ghost" href="#chapters">Browse chapters</a>
</div>
</div>
</header>
<nav class="chapnav" id="chapnav" aria-label="Jump to chapter">
<ul class="chapnav__list">
<li><a href="#starters" class="chapnav__link is-active">Starters</a></li>
<li><a href="#mains" class="chapnav__link">Mains</a></li>
<li><a href="#desserts" class="chapnav__link">Desserts</a></li>
</ul>
<div class="viewtoggle" role="group" aria-label="Choose layout">
<button class="viewtoggle__btn is-active" id="viewGrid" aria-pressed="true">
<span aria-hidden="true">▦</span> Grid
</button>
<button class="viewtoggle__btn" id="viewList" aria-pressed="false">
<span aria-hidden="true">☰</span> List
</button>
</div>
</nav>
<main id="chapters" class="book" data-view="grid">
<section class="chapter" id="starters" aria-labelledby="starters-h">
<div class="chapter__head">
<span class="chapter__num">I</span>
<div>
<h2 class="chapter__title" id="starters-h">Starters</h2>
<p class="chapter__sub">Small, bright plates to wake the table up.</p>
</div>
</div>
<ol class="cards">
<li class="card" tabindex="0">
<span class="card__index">01</span>
<div class="card__photo card__photo--tomato" aria-hidden="true"><span>🍅</span></div>
<div class="card__body">
<h3 class="card__title">Charred Tomato & Burrata Toast</h3>
<p class="card__desc">Blistered cherry tomatoes over creamy burrata on grilled sourdough, finished with basil oil.</p>
<ul class="card__meta">
<li>⏱ 20 min</li><li>🔥 Easy</li><li>🍽 Serves 2</li>
</ul>
</div>
</li>
<li class="card" tabindex="0">
<span class="card__index">02</span>
<div class="card__photo card__photo--sage" aria-hidden="true"><span>🥬</span></div>
<div class="card__body">
<h3 class="card__title">Shaved Fennel & Citrus Salad</h3>
<p class="card__desc">Paper-thin fennel, blood orange, mint and toasted pistachio in a honey-lemon dressing.</p>
<ul class="card__meta">
<li>⏱ 15 min</li><li>🔥 Easy</li><li>🍽 Serves 4</li>
</ul>
</div>
</li>
<li class="card" tabindex="0">
<span class="card__index">03</span>
<div class="card__photo card__photo--saffron" aria-hidden="true"><span>🧄</span></div>
<div class="card__body">
<h3 class="card__title">Saffron Garlic Bean Dip</h3>
<p class="card__desc">Silky white beans whipped with roasted garlic and a thread of saffron, served warm.</p>
<ul class="card__meta">
<li>⏱ 30 min</li><li>🔥 Easy</li><li>🍽 Serves 6</li>
</ul>
</div>
</li>
</ol>
</section>
<section class="chapter" id="mains" aria-labelledby="mains-h">
<div class="chapter__head">
<span class="chapter__num">II</span>
<div>
<h2 class="chapter__title" id="mains-h">Mains</h2>
<p class="chapter__sub">The long, slow centre of the meal.</p>
</div>
</div>
<ol class="cards">
<li class="card" tabindex="0">
<span class="card__index">04</span>
<div class="card__photo card__photo--clay" aria-hidden="true"><span>🍲</span></div>
<div class="card__body">
<h3 class="card__title">Sunday Red Wine Short Ribs</h3>
<p class="card__desc">Beef short ribs braised four hours in red wine, rosemary and a whole head of garlic.</p>
<ul class="card__meta">
<li>⏱ 4h 30m</li><li>🔥 Medium</li><li>🍽 Serves 6</li>
</ul>
</div>
</li>
<li class="card" tabindex="0">
<span class="card__index">05</span>
<div class="card__photo card__photo--saffron" aria-hidden="true"><span>🍋</span></div>
<div class="card__body">
<h3 class="card__title">Lemon & Thyme Roast Chicken</h3>
<p class="card__desc">A whole bird brined overnight, roasted golden with charred lemon and root vegetables.</p>
<ul class="card__meta">
<li>⏱ 1h 50m</li><li>🔥 Medium</li><li>🍽 Serves 4</li>
</ul>
</div>
</li>
<li class="card" tabindex="0">
<span class="card__index">06</span>
<div class="card__photo card__photo--sage" aria-hidden="true"><span>🥕</span></div>
<div class="card__body">
<h3 class="card__title">Smoky Carrot & Lentil Stew</h3>
<p class="card__desc">Roasted carrots and beluga lentils simmered with smoked paprika and a swirl of yoghurt.</p>
<ul class="card__meta">
<li>⏱ 55 min</li><li>🔥 Easy</li><li>🍽 Serves 4</li>
</ul>
</div>
</li>
</ol>
</section>
<section class="chapter" id="desserts" aria-labelledby="desserts-h">
<div class="chapter__head">
<span class="chapter__num">III</span>
<div>
<h2 class="chapter__title" id="desserts-h">Desserts</h2>
<p class="chapter__sub">A sweet, quiet end to a long afternoon.</p>
</div>
</div>
<ol class="cards">
<li class="card" tabindex="0">
<span class="card__index">07</span>
<div class="card__photo card__photo--clay" aria-hidden="true"><span>🍮</span></div>
<div class="card__body">
<h3 class="card__title">Burnt Honey Custard</h3>
<p class="card__desc">A wobbling baked custard under a lid of bitter-sweet burnt honey caramel.</p>
<ul class="card__meta">
<li>⏱ 1h 10m</li><li>🔥 Medium</li><li>🍽 Serves 6</li>
</ul>
</div>
</li>
<li class="card" tabindex="0">
<span class="card__index">08</span>
<div class="card__photo card__photo--tomato" aria-hidden="true"><span>🍓</span></div>
<div class="card__body">
<h3 class="card__title">Roasted Strawberry Galette</h3>
<p class="card__desc">A rustic free-form tart of roasted strawberries and vanilla in flaky butter pastry.</p>
<ul class="card__meta">
<li>⏱ 1h 05m</li><li>🔥 Medium</li><li>🍽 Serves 8</li>
</ul>
</div>
</li>
<li class="card" tabindex="0">
<span class="card__index">09</span>
<div class="card__photo card__photo--saffron" aria-hidden="true"><span>🍪</span></div>
<div class="card__body">
<h3 class="card__title">Olive Oil & Sea Salt Cookies</h3>
<p class="card__desc">Soft, fragrant olive-oil cookies dusted with flaky salt and orange zest.</p>
<ul class="card__meta">
<li>⏱ 40 min</li><li>🔥 Easy</li><li>🍽 Makes 18</li>
</ul>
</div>
</li>
</ol>
</section>
</main>
<footer class="footer" role="contentinfo">
<p>The Slow Sunday Kitchen · An illustrative cookbook collection.</p>
<p class="footer__fine">Recipes & times are fictional and for demonstration only.</p>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Recipe Collection / Cookbook index
A warm, editorial cookbook index built around a single curated collection. The cover pairs a layered gradient “photo” with a serif title, the curator’s name, and a quick summary of how many recipes the book holds and how long it all takes. Below it, recipes are grouped into numbered chapters — Starters, Mains and Desserts — so the page reads like flipping through an actual cookbook.
Each recipe card uses rich CSS gradients and food emoji as appetizing placeholders instead of images, with the dish name in a serif face and time, difficulty and servings underneath. Cards lift on hover and focus, and are fully keyboard-operable.
The interactions are all vanilla JS: a sticky chapter jump-nav with scroll-spy that highlights the section you’re reading, a save-collection button that toggles its state and confirms with a toast, and a grid/list view switch that re-flows the cards between a three-column grid and a single editorial column.
Illustrative UI only — recipes & nutrition data are fictional, not dietary advice.