diff --git a/index.html b/index.html
new file mode 100644
index 000000000..0dc4cd940
--- /dev/null
+++ b/index.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+ Recipe Library
+
+
+
+
+
Recipe Library
+
+
+
+
Filter by cuisine
+
+
+
+
+
+
+
+
+
+
Sort by time
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/script.js b/script.js
new file mode 100644
index 000000000..74744a453
--- /dev/null
+++ b/script.js
@@ -0,0 +1,135 @@
+// --- State ---
+let cuisineQueryParam = ""; // e.g., "&cuisine=italian"
+let sortQueryParam = "&sort=time&sortDirection=desc"; // default by time, descending
+let activeFilterBtn = null;
+let activeSortBtn = null;
+
+const API_KEY = "3f2445631f2d458b92fe40f9832bcc51";
+
+// --- Marks the clicked button as active and removes the active class from the previously clicked one. ---
+function markActive(newBtn, prevBtnRefName) {
+ if (newBtn === null) return;
+ if (window[prevBtnRefName]) {
+ window[prevBtnRefName].classList.remove("active");
+ }
+ newBtn.classList.add("active");
+ window[prevBtnRefName] = newBtn;
+}
+
+//Fetches updated recipes and sends them to the UI rendering function (showCase()).
+function updateAndRender() {
+ showCase(fetchRecipes());
+}
+
+// --- UI Actions Handles what happens when the user clicks a filter button (like “Italian” or “Mexican”).---
+function setActiveFilter(filter) {
+ // Set query param
+ if (filter === "all") {
+ cuisineQueryParam = "";
+ } else {
+ cuisineQueryParam = "&cuisine=" + encodeURIComponent(filter);
+ }
+ // Mark active button
+ const btn = document.getElementById(`filter__${filter}`);
+ markActive(btn, "activeFilterBtn");
+
+ // Refresh results
+ updateAndRender();
+}
+
+function setActiveSort(direction) {
+ // Validate: asc | desc
+ const dir = direction === "asc" ? "asc" : "desc";
+ sortQueryParam = `&sort=time&sortDirection=${dir}`;
+
+ const btn = document.getElementById(`sort__${dir}`);
+ markActive(btn, "activeSortBtn");
+
+ // Refresh results
+ updateAndRender();
+}
+
+// --- Data Fetch recipe from spoonacular API, based on filter and sort settings ---
+async function fetchRecipes() {
+ const URL = `https://api.spoonacular.com/recipes/complexSearch?fillIngredients=true&addRecipeInformation=true&number=12&apiKey=${API_KEY}${cuisineQueryParam}${sortQueryParam}`;
+
+ try {
+ const response = await fetch(URL);
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}`);
+ }
+ const data = await response.json();
+ // data.results is an array of recipe objects
+ return data.results || [];
+ } catch (err) {
+ console.error(err);
+ // Graceful fallback
+ return [];
+ }
+}
+
+// --- Format time, and minustes ---
+function formatTime(totalMinutes) {
+ const h = Math.floor(totalMinutes / 60);
+ const m = totalMinutes % 60;
+ if (h && m) return `${h}h ${m}m`;
+ if (h) return `${h}h`;
+ return `${m}m`;
+}
+
+// Display recepie card in HTML Grid/ CSS style on it
+async function showCase(recipesPromise) {
+ const recipeGrid = document.getElementById("recipe__grid");
+ recipeGrid.innerHTML = `Loading…
`;
+
+ const recipes = await recipesPromise;
+
+ if (!recipes.length) {
+ recipeGrid.innerHTML = `No recipes found. Try a different filter.
`;
+ return;
+ }
+
+ recipeGrid.innerHTML = "";
+
+ recipes.forEach((recipe) => {
+ const recipeCard = document.createElement("div");
+ recipeCard.className = "recipe__card";
+
+ const cuisines =
+ Array.isArray(recipe.cuisines) && recipe.cuisines.length
+ ? recipe.cuisines.join(", ")
+ : "—";
+
+ const ingredients = Array.isArray(recipe.extendedIngredients)
+ ? recipe.extendedIngredients.map((ing) => ing.original)
+ : [];
+
+ const ingredientList = document.createElement("ul");
+ ingredientList.className = "recipe__ingredients";
+ ingredients.forEach((text) => {
+ const li = document.createElement("li");
+ li.textContent = text;
+ ingredientList.appendChild(li);
+ });
+ // html structor
+ recipeCard.innerHTML = `
+
+ ${recipe.title}
+ Cuisine: ${cuisines}
+ Time: ${formatTime(
+ recipe.readyInMinutes || 0
+ )}
+ Ingredients:
+ `;
+
+ recipeCard.appendChild(ingredientList);
+ recipeGrid.appendChild(recipeCard);
+ });
+}
+// initialization (auto-run- on load)
+// --- Init (after DOM is ready because script is at the end of body) ---
+(function init() {
+ // Set defaults visually & load first page
+ setActiveFilter("all");
+ setActiveSort("desc");
+})();
diff --git a/styles.css b/styles.css
new file mode 100644
index 000000000..3cb5dbb2b
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,105 @@
+* {
+ margin: 0;
+}
+
+h1 {
+ color: blue;
+ font-size: 3.5rem;
+ margin-top: 50px;
+ margin-bottom: 50px;
+}
+
+h2 {
+ margin: 25px 0 25px;
+}
+
+#controls {
+ display: flex;
+ justify-content: space-between;
+ max-width: 900px;
+ flex-flow: row wrap;
+}
+
+.controls__container {
+ display: flex;
+ justify-content: start;
+ gap: 30px;
+ flex-wrap: wrap;
+}
+
+.controls__container > button {
+ color: #0018a4;
+ border: none;
+ padding: 15px 32px;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 16px;
+ cursor: pointer;
+ border-radius: 30px;
+}
+.controls__container.filter > button {
+ background-color: #ccffe2;
+}
+.controls__container.filter > button.active {
+ color: white;
+ background-color: #0018a4;
+}
+.controls__container.filter > button:hover {
+ border: 2px blue solid;
+}
+
+.controls__container.sort > button {
+ background-color: #ffecea;
+}
+.controls__container.sort > button.active {
+ background-color: #ff6589;
+}
+.controls__container.sort > button:hover {
+ border: 2px blue solid;
+ background-color: #ff6589;
+}
+
+#recipe__grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
+ margin-top: 2rem;
+ column-gap: 10px;
+ row-gap: 20px;
+}
+
+.recipe__card {
+ display: flex;
+ flex-direction: column;
+ padding: 1rem;
+ /* border: 2px grey solid; */
+ border-radius: 10px;
+ width: 300px;
+ gap: 10px;
+ height: fit-content;
+ box-shadow: 1px 2px 3px 2px #dadada;
+}
+
+.recipe__card > img {
+ border-radius: 20px;
+ align-self: center;
+ max-width: 100%;
+ margin: 16px;
+}
+
+.recipe__card > h3,
+h4 {
+ border-bottom: 1px grey solid;
+ padding-bottom: inherit;
+}
+
+.recipe__card > ul {
+ list-style: none;
+ padding-inline-start: 0px;
+}
+
+.container {
+ /* padding: 20px; */
+ width: 90dvw;
+ margin: 0 auto;
+}