diff --git a/README.md b/README.md index 7d38b84..e5b4e8d 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# project-library \ No newline at end of file +# project-library + +https://xingsbooklibrary.netlify.app \ No newline at end of file diff --git a/assets/facebook-icon.png b/assets/facebook-icon.png new file mode 100644 index 0000000..e2beb5a Binary files /dev/null and b/assets/facebook-icon.png differ diff --git a/assets/github-icon.png b/assets/github-icon.png new file mode 100644 index 0000000..fe3ad98 Binary files /dev/null and b/assets/github-icon.png differ diff --git a/assets/instagram-icon.png b/assets/instagram-icon.png new file mode 100644 index 0000000..ecdc0c6 Binary files /dev/null and b/assets/instagram-icon.png differ diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..94f82df Binary files /dev/null and b/assets/logo.png differ diff --git a/assets/search-icon.png b/assets/search-icon.png new file mode 100644 index 0000000..c83ebcb Binary files /dev/null and b/assets/search-icon.png differ diff --git a/assets/twitter-icon.png b/assets/twitter-icon.png new file mode 100644 index 0000000..84d3485 Binary files /dev/null and b/assets/twitter-icon.png differ diff --git a/books-images/harry-potter-and-the-sorcerer.jpg b/books-images/harry-potter-and-the-sorcerer.jpg deleted file mode 100644 index 05d8a24..0000000 Binary files a/books-images/harry-potter-and-the-sorcerer.jpg and /dev/null differ diff --git a/index.html b/index.html index cf5c31a..3f27a10 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,76 @@ + - - Project Library + + XingS Book Library + + -

Project Library

- +
+

Book Library

+ +
+ + +
+ + + + + + \ No newline at end of file diff --git a/pull_request_template.md b/pull_request_template.md index d92c89b..85271bd 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,7 +1,5 @@ ## Netlify link -Add your Netlify link here. -PS. Don't forget to add it in your readme as well. +https://xingsbooklibrary.netlify.app ## Collaborators -Add your collaborators here. Write their GitHub usernames in square brackets. If there's more than one, separate them with a comma, like this: -[github-username-1, github-username-2] +SOLO diff --git a/recipe-images/baked-chicken.jpg b/recipe-images/baked-chicken.jpg deleted file mode 100644 index b580fdc..0000000 Binary files a/recipe-images/baked-chicken.jpg and /dev/null differ diff --git "a/recipe-images/cheat\342\200\231s-cheesy-focaccia.jpg" "b/recipe-images/cheat\342\200\231s-cheesy-focaccia.jpg" deleted file mode 100644 index 4a6128e..0000000 Binary files "a/recipe-images/cheat\342\200\231s-cheesy-focaccia.jpg" and /dev/null differ diff --git a/recipe-images/chicken-paprikash.jpg b/recipe-images/chicken-paprikash.jpg deleted file mode 100644 index 361e5fe..0000000 Binary files a/recipe-images/chicken-paprikash.jpg and /dev/null differ diff --git a/recipe-images/deep-fried-fish-bones.jpg b/recipe-images/deep-fried-fish-bones.jpg deleted file mode 100644 index d9ed554..0000000 Binary files a/recipe-images/deep-fried-fish-bones.jpg and /dev/null differ diff --git a/recipe-images/fish-dish.jpg b/recipe-images/fish-dish.jpg deleted file mode 100644 index 4166fb7..0000000 Binary files a/recipe-images/fish-dish.jpg and /dev/null differ diff --git a/recipe-images/grilled.jpg b/recipe-images/grilled.jpg deleted file mode 100644 index fe7a433..0000000 Binary files a/recipe-images/grilled.jpg and /dev/null differ diff --git a/recipe-images/individual-vegetarian-lasagnes.jpg b/recipe-images/individual-vegetarian-lasagnes.jpg deleted file mode 100644 index 58fab20..0000000 Binary files a/recipe-images/individual-vegetarian-lasagnes.jpg and /dev/null differ diff --git a/recipe-images/meat.jpg b/recipe-images/meat.jpg deleted file mode 100644 index b1896d9..0000000 Binary files a/recipe-images/meat.jpg and /dev/null differ diff --git a/recipe-images/vegetarian-shepherd's-pie.jpg b/recipe-images/vegetarian-shepherd's-pie.jpg deleted file mode 100644 index a6d811a..0000000 Binary files a/recipe-images/vegetarian-shepherd's-pie.jpg and /dev/null differ diff --git a/recipe-images/vegetarian-stir-fried-garlic-s.jpg b/recipe-images/vegetarian-stir-fried-garlic-s.jpg deleted file mode 100644 index 86babc8..0000000 Binary files a/recipe-images/vegetarian-stir-fried-garlic-s.jpg and /dev/null differ diff --git a/script.js b/script.js index 6a61c06..0160441 100644 --- a/script.js +++ b/script.js @@ -1,8 +1,4 @@ -/*Here we have created two different arrays that you can work with if you want. -If you choose to create your own arrays with elements, just make sure that some -of the properties make sense to filter on, and some to sort on.*/ - -const books = [ +const BOOKS = [ { title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', @@ -63,17 +59,7 @@ const books = [ 'A fantasy adventure novel that follows Bilbo Baggins on a quest to help a group of dwarves reclaim their homeland from a dragon.', image: './books-images/the-hobbit.jpg' }, - { - title: "Harry Potter and the Sorcerer's Stone", - author: 'J.K. Rowling', - year: 1997, - genre: 'Fantasy', - rating: 4.7, - description: - 'The first book in the beloved Harry Potter series, it introduces readers to the magical world of Hogwarts and the young wizard Harry Potter.', - image: "./books-images/harry-potter-and-the-sorcerer'.jpg" - }, - { + { title: 'Moby-Dick', author: 'Herman Melville', year: 1851, @@ -163,16 +149,6 @@ const books = [ "Set in a post-apocalyptic world, it follows a father and son's harrowing journey to survive and find safety.", image: './books-images/unknown.jpg' }, - { - title: "The Hitchhiker's Guide to the Galaxy", - author: 'Douglas Adams', - year: 1979, - genre: 'Science Fiction', - rating: 4.35, - description: - "A comedic science fiction series that follows the misadventures of Arthur Dent after Earth's destruction.", - image: './books-images/unknown.jpg' - }, { title: 'The Giver', author: 'Lois Lowry', @@ -185,222 +161,182 @@ const books = [ } ] -const recipes = [ - { - name: 'Individual vegetarian lasagnes', - cuisineType: ['italian'], - ingredients: [ - '1.2 kg cherry tomatoes', - '5 sprigs of fresh thyme', - 'extra virgin olive oil', - '2 shallots', - '2 cloves of garlic', - '500 g baby spinach', - '8-12 fresh or dried lasagne sheets', - '350 g ricotta cheese', - 'WHITE SAUCE', - '600 ml milk', - '25 g unsalted butter', - '2 heaped tablespoons flour', - '150 g vegetarian sharp, mature cheese', - '100 g mozzarella' - ], - source: 'Jamie Oliver', - totalTime: 130, - url: 'http://www.jamieoliver.com/recipes/vegetables-recipes/individual-vegetarian-lasagnes/', - image: './recipe-images/individual-vegetarian-lasagnes.jpg' - }, - { - name: 'Vegetarian Stir-Fried Garlic Scape', - cuisineType: ['Balanced'], - ingredients: [ - '8 oz. garlic scapes', - '3 oz. baby corn', - '3 oz. carrots', - '1 oz. dried shiitake mushrooms', - '1 clove of garlic sliced thinly', - '3 slices of fresh ginger root', - '2 tablespoons vegetable oil', - '1/4 cup shaoxing cooking wine', - '1/4 vegetarian stock or water', - '1 tablespoon light soy sauce', - '1 teaspoon sugar', - '1 teaspoon cornstarch', - '1/4 teaspoon ground white pepper' - ], - source: 'Red Cook', - totalTime: null, - url: 'http://redcook.net/2010/06/16/garlic-scape-an-off-menu-treat/', - image: './recipe-images/vegetarian-stir-fried-garlic-s.jpg' - }, - { - name: 'Cheat’s cheesy focaccia', - cuisineType: ['Italian'], - ingredients: [ - '500g pack bread mix', - '2 tbsp olive oil , plus a little extra for drizzling', - '25g parmesan (or vegetarian alternative), grated', - '75g dolcelatte cheese (or vegetarian alternative)' - ], - source: 'BBC Good Food', - totalTime: 40, - url: 'https://www.bbcgoodfood.com/recipes/cheats-cheesy-focaccia', - image: './recipe-images/cheat’s-cheesy-focaccia.jpg' - }, - { - name: "Vegetarian Shepherd's Pie", - cuisineType: ['Balanced', 'High-Fiber'], - ingredients: [ - '2 tablespoons extra-virgin olive oil', - '1 large onion, finely diced', - '2 carrots, peeled and thinly sliced', - '2 celery stalks, thinly sliced', - '10 ounces cremini mushrooms, trimmed and sliced', - '1 tablespoon tomato paste', - "1 tablespoon vegetarian Worcestershire sauce, such as Annie's Naturals", - '1 dried bay leaf', - '1 cup French green lentils, picked over', - 'Kosher salt and freshly ground pepper', - '1 cup frozen peas', - '2 pounds Yukon Gold potatoes, scrubbed and cut into 1 1/2-inch pieces', - '4 cloves garlic', - '4 tablespoons unsalted butter', - '1/2 cup whole milk, warmed' - ], - source: 'Martha Stewart', - totalTime: 120, - url: 'https://www.marthastewart.com/1535235/vegetarian-shepherds-pie', - image: "./recipe-images/vegetarian-shepherd's-pie.jpg" - }, - { - name: 'Chicken Paprikash', - cuisineType: ['Low-Carb'], - ingredients: [ - '640 grams chicken - drumsticks and thighs ( 3 whole chicken legs cut apart)', - '1/2 teaspoon salt', - '1/4 teaspoon black pepper', - '1 tablespoon butter – cultured unsalted (or olive oil)', - '240 grams onion sliced thin (1 large onion)', - '70 grams Anaheim pepper chopped (1 large pepper)', - '25 grams paprika (about 1/4 cup)', - '1 cup chicken stock', - '1/2 teaspoon salt', - '1/2 cup sour cream', - '1 tablespoon flour – all-purpose' - ], - source: 'No Recipes', - totalTime: 80, - url: 'http://norecipes.com/recipe/chicken-paprikash/', - image: './recipe-images/chicken-paprikash.jpg' - }, - { - name: 'Baked Chicken', - cuisineType: ['american'], - ingredients: [ - '6 bone-in chicken breast halves, or 6 chicken thighs and wings, skin-on', - '1/2 teaspoon coarse salt', - '1/2 teaspoon Mrs. Dash seasoning', - '1/4 teaspoon freshly ground black pepper' - ], - source: 'Martha Stewart', - totalTime: 90, - url: 'http://www.marthastewart.com/318981/baked-chicken', - image: './recipe-images/baked-chicken.jpg' - }, - { - name: 'Deep Fried Fish Bones', - cuisineType: ['south east asian'], - ingredients: ['8 small whiting fish or smelt', '4 cups vegetable oil'], - source: 'Serious Eats', - totalTime: 31, - url: 'http://www.seriouseats.com/recipes/2011/03/deep-fried-fish-bones-recipe.html', - image: './recipe-images/deep-fried-fish-bones.jpg' - }, - { - name: 'Burnt-Scallion Fish', - cuisineType: ['chinese'], - ingredients: [ - '2 bunches scallions', - '8 tbsp. butter', - '2 8-oz. fish filets' - ], - source: 'Saveur', - totalTime: 70, - url: 'http://www.saveur.com/article/Recipes/Burnt-Scallion-Fish', - image: './recipe-images/fish-dish.jpg' - }, - { - name: 'Curry-Crusted Fish', - cuisineType: ['south east asian'], - ingredients: [ - '3 slices bread , about 85g/3oz in total', - '1 lime', - '1.0 tbsp Korma curry paste', - '4 thick white fish fillets' - ], - source: 'BBC Good Food', - totalTime: 80, - url: 'http://www.bbcgoodfood.com/recipes/4717/', - image: './recipe-images/fish-dish.jpg' - }, - { - name: 'Meat Stock', - cuisineType: 'american', - ingredients: [ - '2.5 pounds beef marrow bones', - '1 large onion, quartered', - '2 carrots, sliced', - '1 leek, cleaned and sliced', - '2 celery stalks, sliced', - '2.5 pounds organic beef stew meat, cubed', - '2 tablespoons tomato paste', - '5 cloves garlic', - '2 bay leaves', - '3 sprigs thyme', - '3 sprigs Italian parsley', - '1/2 teaspoon black peppercorns' - ], - source: 'Food52', - totalTime: 60, - url: 'https://food52.com/recipes/3712-meat-stock', - image: './recipe-images/meat.jpg' - }, - { - name: 'Homemade Meat Broth', - cuisineType: 'american', - ingredients: [ - '1 teaspoon salt', - '1 carrot, peeled', - '1 medium onion, peeled', - '2 or 3 celery stalks', - '¼ red or yellow bell pepper, stripped of all its seeds', - '1 small boiling potato, peeled', - '1 ripe, fresh tomato, or 1 canned Italian plum tomato, drained of juice', - '5 pounds assorted pieces of meat and bones (see meat suggestions above), of which no less than 1½ pounds is all meat' - ], - source: 'Cookstr', - totalTime: 60, - url: 'http://www.cookstr.com/recipes/il-brodo-homemade-meat-broth', - image: './recipe-images/meat.jpg' - }, - { - name: 'Spice-Rubbed Grilled Flap Meat (Sirloin Tip) Recipe', - cuisineType: 'south-american', - ingredients: [ - '1 tablespoon whole black peppercorns, toasted', - '1 teaspoon coriander seed, toasted', - '1 teaspoon fennel seed, toasted', - '1 teaspoon cumin pods, toasted', - '1 teaspoon red pepper flakes', - '1/2 teaspoon dried oregano', - '2 medium cloves garlic, minced (about 2 teaspoons)', - '2 tablespoons vegetable or canola oil', - '1 whole flap meat steak, 2 to 2 1/2 pounds', - 'Kosher salt' - ], - source: 'Serious Eats', - totalTime: 240, - url: 'http://www.seriouseats.com/recipes/2012/05/spice-rubbed-grilled-flap-meat-sirloin-tip-recipe.html', - image: './recipe-images/grilled.jpg' +const container = document.getElementById("container") +const filterDropdown = document.getElementById("dropdown") +const favouritesContainer = document.getElementById("favourites") +const favList = document.getElementById('favouriteList') +const sortContainer = document.getElementById("sortContainer") +const resetButton = document.getElementById('resetButton'); + +let favouriteBooks = [] // Array to store favorite books + +/** + * DISPLAY FUNCTIONS + */ + +// Function to display books +const getBooks = (bookArray) => { + container.innerHTML = "" // Clean up the container + bookArray.forEach(book => { + const isFavourite = favouriteBooks.includes(book) // Check if the book is a favorite + const buttonText = isFavourite + ? "Remove from Favourites" + : "Add to Favourites" // Change the text on the favo button + + container.innerHTML += ` +
+ ${book.title} +

${book.title}

+
+

Author: ${book.author}

+

Year: ${book.year}

+

Genre: ${book.genre}

+

Rating: ${book.rating}

+ + + +
` + }) +} + +// Function to display favorite books in the ham menu +const displayFavourites = () => { + favList.innerHTML = "" // Clean up the fav list + + if (favouriteBooks.length > 0) { + // Add the heading "Your favourite books" only if there are favorite books + favList.innerHTML += `

Your favourite books:

` + + favouriteBooks.forEach(book => { + favList.innerHTML += `
  • ${book.title}
  • ` + }) + } else { + // Display a message if no favorite books are added yet + favList.innerHTML += `

    No favourite books added yet.

    ` } -] +} + +/** + * TOGGLING FUNCTIONS + */ + +// Function to toggle Read More +const toggleDescription = (bookTitle) => { + const descriptionElement = document.getElementById(`desc-${bookTitle}`) + if (descriptionElement.style.display === "none") { + descriptionElement.style.display = "block" + } else { + descriptionElement.style.display = "none" + } +} + +// Function to toggle the favorite books menu visibility (ham menu) +const toggleFavouriteMenu = () => { + favouritesContainer.classList.toggle('show') // Toggle the 'show' class +} + +// Function to toggle favourite books (add/remove) +const toggleFavourite = (bookTitle) => { + const book = BOOKS.find(book => book.title === bookTitle) + const bookIndex = favouriteBooks.indexOf(book) + + if (bookIndex > -1) { + favouriteBooks.splice(bookIndex,1) // If the book is already in the favorites, remove it + } else { + favouriteBooks.push(book) // Otherwise, add it to the favorites + } + + getBooks(BOOKS) // Refresh the book list + displayFavourites() // Update the favorite books list +} + +/** + * SORTING AND FILTERING FUNCTIONS + */ + +// Function to filter books based on genre +const filterBooks = () => { + // get the value from the select + const value = filterDropdown.value + if (value === "all") { + getBooks(BOOKS) // Display all books + } else { + const filteredList = BOOKS.filter(book => book.genre === value) // Filter books by genre + getBooks(filteredList) + } +} + +// Global sorting function +const sortBooksBy = (value) => { + let sortedBooks + + switch (value) { + case 'year-desc': + sortedBooks = BOOKS.slice().sort((a, b) => b.year - a.year) + break + + case 'year-asc': + sortedBooks = BOOKS.slice().sort((a, b) => a.year - b.year) + break + + case 'rating-low-high': + sortedBooks = BOOKS.slice().sort((a, b) => a.rating - b.rating) + break + + case 'rating-high-low': + sortedBooks = BOOKS.slice().sort((a, b) => b.rating - a.rating) + break + } + + getBooks(sortedBooks) // Re-render the books +} + +/** + * INITIALIZATION AND EVENT LISTENERS + */ + +// Function to render the sort menu and toggle visibility +const toggleSortMenu = () => { + sortContainer.innerHTML = "" // Clean up the sort container + + // Add the button and the sort menu dynamically + sortContainer.innerHTML += ` + + ` + + // Add click event listener to the sort button for toggling menu vsibility + const sortToggleButton = document.getElementById("sortToggle") + sortToggleButton.addEventListener("click", () => { + const sortMenu = document.getElementById("sortMenu") + sortMenu.style.display = (sortMenu.style.display === "none" || sortMenu.style.display === "") + ? "block" + : "none"; + }) +} + +// Event listener for the reset button +resetButton.addEventListener('click', () => { + location.reload(); // Refreshes the page +}); + +// Initialize sorting and book rendering +filterDropdown.addEventListener("change", filterBooks) +toggleSortMenu() +getBooks(BOOKS) \ No newline at end of file diff --git a/style.css b/style.css index e69de29..1784e6b 100644 --- a/style.css +++ b/style.css @@ -0,0 +1,390 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +:root { + --white:#fff; + --light-grey:#bbb; + --black:#000; + --dark-grey:#333; + --grey:#555; + --blue:#0018A4; + --light-blue:#ccffe2; + --pink: #ff6589; + --light-pink:#ffecea; +} + +body { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + height: 100vh; +} + +.hidden { + display: none; +} + +/* +************* style for header and nav *************** +*/ + +/* Header styles */ +.header { + background-color: var(--pink); + color: var(--white); + padding: 20px; + display: flex; + flex-direction: column; + justify-content: center; +} + +/* Navigation bar */ +.nav { + display: flex; + align-items: center; + gap: 10px; + margin-top: 10px; +} + +/* Dropdown and search input styling */ +#dropdown, #searchInput { + padding: 0.5rem 1rem; + border-radius: 20px; + border: 2px solid var(--pink); + background-color: var(--white); + color: var(--blue); + font-size: 1rem; + margin-right: 10px; + outline: none; + max-width: 100%; +} + +#dropdown:hover, #searchInput:hover { + background-color: var(--light-pink); + border-color: var(--blue); +} + +#dropdown:focus, #searchInput:focus { + outline: 2px solid var(--blue); +} + +.sort-container { + position: relative; +} + +.sort-toggle { + background-color: var(--light-pink); + color: var(--blue); + padding: 0.5rem 1rem; + border: none; + border-radius: 20px; + cursor: pointer; + font-size: 1rem; + display: inline-block; + text-align: center; + transition: background-color 0.3s ease; +} + +.sort-toggle:hover { + background-color: var(--pink); + color: var(--white); + outline: solid 2px var(--blue); +} + +/* Sort menu (hidden by default) */ +.sort-menu { + display: none; /* Hidden initially */ + background-color: var(--light-pink); + color: var(--blue); + padding: 10px; + border-radius: 10px; + position: absolute; + top: 50px; + left: 0; + z-index: 1; + width: 200px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + text-align: left; +} + +.sort-menu.show { + display: block; /* Show the menu when toggled */ +} + +/* Style for each label */ +.sort-menu label { + display: block; + font-size: 1rem; /* Ensure readability */ + line-height: 1.5; /* Adjust line height for better spacing */ + color: var(--blue); +} + +.sort-menu label:hover { + color: var(--pink); /* Add hover effect for better interaction */ +} + +.sort-menu input { + margin-right: 10px; /* Add space between radio button and text */ +} + +/* Hamburger menu styling */ +#favourites { + position: fixed; + right: 0; + top: 0; + background-color: rgba(0, 0, 0, 0.8); + color: var(--white); + padding: 20px; + min-width: 200px; + height: 100%; + z-index: 100; + display: none; + overflow-y: auto; +} + +#favourites.show { + display: block; /* Make the favourites menu visible */ +} + +/* Hamburger menu */ +.hamburger-menu { + cursor: pointer; + width: 30px; + height: 30px; + position: relative; + z-index: 200; /* Ensure it's always on top of the fav list */ +} + +.hamburger-menu::before { + content: "❤️"; + font-size: 1.5rem; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; + text-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + transition: opacity 0.1s ease; +} + +/* Hide the heart on hover */ +.hamburger-menu:hover::before { + opacity: 0; /* Hides the heart when hovered */ + transition: opacity 0.1s ease; /* Smooth transition */ +} + +/* Define the X bars (initially hidden) */ +.hamburger-menu .bar1, +.hamburger-menu .bar2 { + width: 100%; + height: 4px; + background-color: var(--white); + margin: 6px 0; + transition: transform 0.3s ease; + transform-origin: center; + opacity: 0; /* Hide bars initially */ +} + +/* Display the X bars when hovered */ +.hamburger-menu:hover .bar1, .hamburger-menu:hover .bar2 { + opacity: 1; /* Show bars */ + transition: opacity 0.3s ease; /* Smooth transition */ +} + +/* X transformation on hover */ +.hamburger-menu:hover .bar1 { + transform: rotate(45deg) translate(5px, 5px); +} + +.hamburger-menu:hover .bar2 { + transform: rotate(-45deg) translate(5px, -5px); +} + +/* Responsive adjustments for smaller screens */ + +@media (max-width: 868px) { + nav{ + display: flex; + flex-flow: column wrap; + justify-content: flex-start; + width: 100%; + } + + #resetButton, + #dropdown, + #sortContainer, + #searchInput { + width: 100%; + align-self: start; + } + + /* Ensure the hamburger menu remains in the top corner and is always visible */ + .hamburger-menu { + position: fixed; /* Keep it fixed so it's always on screen */ + top: 20px; + right: 20px; + z-index: 200; /* Maintain a higher z-index */ + } +} + +/* Styling the reset button */ +.reset-btn { + background-color: var(--light-pink); + color: var(--blue); + padding: 0.5rem 1rem; + border-radius: 20px; + border: none; + cursor: pointer; + font-size: 1rem; + transition: background-color 0.3s ease; +} + +.reset-btn:hover { + background-color: var(--pink); + color: var(--white); + outline: solid 2px var(--blue); +} + +/* +************* style for book card *************** +*/ +#container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); + gap: 1rem; + margin-top: 1rem; +} + +.card { + display: flex; + flex-direction: column; + align-items: center; + background-color: var(--white); + padding: 1rem; + padding-bottom: 1.5rem; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + transition: box-shadow 0.3s ease, transform 0.3s ease; +} + +.card:hover { + box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2); + transform: translateY(-5px); + outline: solid 2px var(--blue) ; +} + +.card img { + width: 100%; + height: auto; + max-height: 180px; + object-fit: cover; + border-radius: 4px; +} + +.card h2 { + margin-top: 1rem; + font-size: 1.25rem; + color: #2c3e50; + text-align: center; + height: 3rem; /* Fixed height to align all titles */ + line-height: 1.5rem; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; /* Limit to 2 lines */ + -webkit-box-orient: vertical; + white-space: normal; /* Allow wrapping */ +} + +/*Add a Grey Line inbetween*/ +.card hr { + width: 40%; + border: 0; + border-top: 1px solid var(--grey); + margin-bottom: 20px; +} + +.card p { + font-size: 1rem; + color: var(--dark-grey); + margin: 1px; +} + +.card p b { + color: var(--blue); + text-align: left; +} + +.card button { + background-color: var(--blue); + color: var(--white); + border: none; + border-radius: 8px; + padding: 0.5rem 1rem; + font-size: 0.9rem; + cursor: pointer; + margin-top: 1rem; + transition: background-color 0.3s ease; +} + +.card button:hover { + background-color: var(--light-blue); + color: var(--blue); +} + +.card button:focus { + outline: solid 2px var(--blue); +} + +/* +**************** footer style *********************** +*/ + +.footer-container { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + margin-top: 16px; +} + +.social-media { + display: flex; + padding: 10px; +} + +.social-media a { + margin-left: 10px; +} + +.social-media img { + max-width: 20px; +} + +.logo img { + max-width: 50px; + padding-left: 15px; +} + +.footer-bottom { + text-align: center; + margin-top: 20px; + font-size: 14px; + color: #bbb; +} + +@media (max-width: 600px) { + footer { + display: flex; + flex-flow: column wrap; + justify-content: center; + align-items: center; + } +} + +@media (min-width: 1025px) { + footer { + padding: 20px 0; + } +} \ No newline at end of file