polished webspages and completed implementation.

This commit is contained in:
George Birikorang 2025-08-19 05:16:00 -04:00
parent 23791a2768
commit 9a3a106fca
7 changed files with 1194 additions and 172 deletions

BIN
assets/icons/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

194
blog.html
View file

@ -9,6 +9,18 @@
content="Read our latest blog posts about furniture design and interior styling." content="Read our latest blog posts about furniture design and interior styling."
/> />
<link rel="stylesheet" href="styles/main.css" /> <link rel="stylesheet" href="styles/main.css" />
<style>
/* Smooth scrolling for the entire page */
html {
scroll-behavior: smooth;
}
/* Active navigation link styling */
.nav-link.active {
color: #b8873f !important;
font-weight: 500;
}
</style>
<link <link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Playfair+Display:wght@100;200;300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Playfair+Display:wght@100;200;300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap"
rel="stylesheet" rel="stylesheet"
@ -35,56 +47,56 @@
<li> <li>
<a <a
href="index.html" href="index.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Home</a >Home</a
> >
</li> </li>
<li> <li>
<a <a
href="products.html" href="index.html#products"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Products</a >Products</a
> >
</li> </li>
<li> <li>
<a <a
href="projects.html" href="index.html#projects-button"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Projects</a >Projects</a
> >
</li> </li>
<li> <li>
<a <a
href="clients.html" href="index.html#clients"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Clients</a >Clients</a
> >
</li> </li>
<li> <li>
<a <a
href="about.html" href="index.html#about"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>About</a >About</a
> >
</li> </li>
<li> <li>
<a <a
href="contact.html" href="contact.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Contact</a >Contact</a
> >
</li> </li>
<li> <li>
<a <a
href="blog.html" href="blog.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Blog</a >Blog</a
> >
</li> </li>
<li> <li>
<a <a
href="quote.html" href="quote.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Quote</a >Quote</a
> >
</li> </li>
@ -126,9 +138,9 @@
<div class="max-w-7xl mx-auto px-5"> <div class="max-w-7xl mx-auto px-5">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-16"> <div class="grid grid-cols-1 lg:grid-cols-3 gap-16">
<!-- Main Blog Content --> <!-- Main Blog Content -->
<div class="lg:col-span-2"> <div id="main-blog-content" class="lg:col-span-2">
<!-- Blog Post --> <!-- Blog Post -->
<article class="mb-16"> <article class="mb-16" data-tags="wood" data-date="2022-10-14">
<!-- Featured Image --> <!-- Featured Image -->
<div class="mb-8"> <div class="mb-8">
<img <img
@ -202,33 +214,79 @@
</p> </p>
<!-- Read More Link --> <!-- Read More Link -->
<a <button
href="#" type="button"
class="inline-block font-playfair font-normal text-base text-black border-b border-black hover:text-gray-600 hover:border-gray-600 transition-colors" class="read-more-toggle inline-block font-playfair font-normal text-base text-black border-b border-black hover:text-gray-600 hover:border-gray-600 transition-colors"
> >
Read more Read more
</a> </button>
<!-- Full content (initially hidden) -->
<div
class="full-content hidden font-playfair font-normal text-base leading-relaxed text-gray-500 mt-6 text-justify"
>
<p class="mb-4">
Quis hendrerit dolor magna eget est lorem ipsum. Bibendum
arcu vitae elementum curabitur vitae nunc sed velit
dignissim sodales. Non tellus orci ac auctor augue mauris
augue neque gravida in. Nisl condimentum id venenatis a
condimentum vitae sapien pellentesque habitant. Sit amet
volutpat consequat mauris nunc congue nisi vitae suscipit.
Integer enim neque volutpat ac tincidunt vitae semper quis
lectus. Nibh tellus molestie nunc non blandit massa enim
nec. Amet consectetur adipiscing elit ut aliquam purus sit
amet luctus.
</p>
<p class="mb-4">
At tellus at urna condimentum mattis pellentesque id nibh
tortor id. Non quam lacus suspendisse faucibus interdum.
Interdum velit euismod in pellentesque massa placerat duis
ultricies. Platea dictumst quisque sagittis purus sit amet
volutpat consequat. Sem viverra aliquet eget sit amet tellus
cras adipiscing. Eget lorem dolor sed viverra ipsum nunc
aliquet bibendum enim facilisis gravida neque convallis a
cras.
</p>
<p>
Mattis rhoncus urna neque viverra justo nec. Aliquet
porttitor lacus luctus accumsan tortor posuere ac ut
consequat semper viverra nam libero justo laoreet sit amet
cursus sit amet dictum sit amet justo. Risus at ultrices mi
tempus imperdiet nulla malesuada pellentesque elit.
</p>
</div>
</article> </article>
<!-- Pagination --> <!-- Pagination -->
<div class="flex items-center justify-center space-x-4"> <div
id="blog-pagination"
class="flex items-center justify-center space-x-4"
>
<button <button
class="w-15 h-15 bg-uc-gold text-white font-playfair font-normal text-xl rounded-lg" type="button"
data-page="1"
class="blog-page-btn inline-flex items-center justify-center px-6 py-2 bg-uc-gold text-white font-playfair font-normal text-xl rounded-full shadow-sm"
> >
1 1
</button> </button>
<button <button
class="w-15 h-15 bg-linen text-black font-playfair font-normal text-xl rounded-lg hover:bg-uc-gold hover:text-white transition-all" type="button"
data-page="2"
class="blog-page-btn inline-flex items-center justify-center px-6 py-2 bg-linen text-black font-playfair font-normal text-xl rounded-full hover:bg-uc-gold hover:text-white transition-all shadow-sm"
> >
2 2
</button> </button>
<button <button
class="w-15 h-15 bg-linen text-black font-playfair font-normal text-xl rounded-lg hover:bg-uc-gold hover:text-white transition-all" type="button"
data-page="3"
class="blog-page-btn inline-flex items-center justify-center px-6 py-2 bg-linen text-black font-playfair font-normal text-xl rounded-full hover:bg-uc-gold hover:text-white transition-all shadow-sm"
> >
3 3
</button> </button>
<button <button
class="px-8 h-15 bg-linen text-black font-playfair font-normal text-xl rounded-lg hover:bg-uc-gold hover:text-white transition-all" type="button"
id="blog-next-btn"
class="inline-flex items-center justify-center px-6 py-2 bg-linen text-black font-playfair font-normal text-xl rounded-full hover:bg-uc-gold hover:text-white transition-all shadow-sm"
> >
Next Next
</button> </button>
@ -241,6 +299,7 @@
<div class="bg-white p-6 rounded-lg shadow-sm mb-8"> <div class="bg-white p-6 rounded-lg shadow-sm mb-8">
<div class="relative"> <div class="relative">
<input <input
id="blog-search-input"
type="text" type="text"
placeholder="Search..." placeholder="Search..."
class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold pr-12" class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold pr-12"
@ -259,56 +318,19 @@
Categories Categories
</h3> </h3>
<div class="space-y-4"> <div class="space-y-4">
<div class="flex justify-between items-center"> <button
<span type="button"
class="font-playfair font-normal text-base text-gray-500" class="flex justify-between items-center w-full text-left tag-filter px-4 py-3 rounded-lg border border-gray-300 hover:border-uc-gold hover:bg-gray-50 transition-colors"
>Crafts</span data-tag="wood"
aria-pressed="false"
> >
<span <span class="font-playfair font-normal text-base">
class="font-playfair font-normal text-base text-gray-500" Wood
>(2)</span </span>
> <span class="font-playfair font-normal text-base">
</div> (1)
<div class="flex justify-between items-center"> </span>
<span </button>
class="font-playfair font-normal text-base text-gray-500"
>Design</span
>
<span
class="font-playfair font-normal text-base text-gray-500"
>(8)</span
>
</div>
<div class="flex justify-between items-center">
<span
class="font-playfair font-normal text-base text-gray-500"
>Handmade</span
>
<span
class="font-playfair font-normal text-base text-gray-500"
>(7)</span
>
</div>
<div class="flex justify-between items-center">
<span
class="font-playfair font-normal text-base text-gray-500"
>Interior</span
>
<span
class="font-playfair font-normal text-base text-gray-500"
>(1)</span
>
</div>
<div class="flex justify-between items-center">
<span
class="font-playfair font-normal text-base text-gray-500"
>Wood</span
>
<span
class="font-playfair font-normal text-base text-gray-500"
>(6)</span
>
</div>
</div> </div>
</div> </div>
@ -321,7 +343,7 @@
<!-- Recent Post 1 --> <!-- Recent Post 1 -->
<div class="flex space-x-4"> <div class="flex space-x-4">
<img <img
src="assets/images/blog_thumb_1.jpg" src="assets/images/blog_thumb_1.png"
alt="Blog thumbnail" alt="Blog thumbnail"
class="w-20 h-20 object-cover rounded-lg" class="w-20 h-20 object-cover rounded-lg"
/> />
@ -347,32 +369,40 @@
</main> </main>
<!-- Footer --> <!-- Footer -->
<footer class="bg-white"> <footer class="bg-white border-t border-black border-opacity-20">
<!-- Main Footer Content --> <!-- Main Footer Content -->
<div class="max-w-7xl mx-auto px-5 py-16"> <div class="max-w-7xl mx-auto px-5 py-16">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<!-- Company Information --> <!-- Company Information -->
<div class="space-y-2"> <div class="space-y-1">
<!-- Logo --> <!-- Logo -->
<div class="w-16 h-20"> <div class="w-16 h-20 -mt-6">
<a
href="index.html"
aria-label="Go to KHY home"
title="KHY Home"
class="inline-block w-full h-full group focus:outline-none focus-visible:ring-2 focus-visible:ring-uc-gold rounded-md transition"
>
<img <img
src="assets/images/khy_logo.png" src="assets/images/khy_logo.png"
alt="khy" alt="KHY logo"
class="w-full h-full object-contain" loading="lazy"
class="w-full h-full object-contain transition-transform duration-300 group-hover:scale-105"
/> />
</a>
</div> </div>
<!-- Address --> <!-- Address -->
<p <p
class="font-playfair font-normal text-base leading-relaxed text-gray-600" class="font-playfair font-normal text-base leading-relaxed text-gray-600 -mt-4"
> >
5 Labone Crescent, Greater Accra, Ghana 5 Labone Crescent, Greater Accra, Ghana
</p> </p>
<!-- Contact Info --> <!-- Contact Info -->
<div class="space-y-1"> <div class="space-y-1 -mt-2">
<!-- Phone --> <!-- Phone -->
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3 -mt-1">
<img <img
src="assets/images/phone.png" src="assets/images/phone.png"
alt="Phone" alt="Phone"
@ -384,7 +414,7 @@
</div> </div>
<!-- Email --> <!-- Email -->
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3 -mt-1">
<img src="assets/images/mail.png" alt="Email" class="w-4 h-4" /> <img src="assets/images/mail.png" alt="Email" class="w-4 h-4" />
<span class="font-playfair font-normal text-base text-gray-800"> <span class="font-playfair font-normal text-base text-gray-800">
design@khyltd.com design@khyltd.com

View file

@ -9,6 +9,18 @@
content="Get in touch with KHY for professional furniture and design services." content="Get in touch with KHY for professional furniture and design services."
/> />
<link rel="stylesheet" href="styles/main.css" /> <link rel="stylesheet" href="styles/main.css" />
<style>
/* Smooth scrolling for the entire page */
html {
scroll-behavior: smooth;
}
/* Active navigation link styling */
.nav-link.active {
color: #b8873f !important;
font-weight: 500;
}
</style>
<link <link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Playfair+Display:wght@100;200;300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Playfair+Display:wght@100;200;300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap"
rel="stylesheet" rel="stylesheet"
@ -35,56 +47,56 @@
<li> <li>
<a <a
href="index.html" href="index.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Home</a >Home</a
> >
</li> </li>
<li> <li>
<a <a
href="products.html" href="index.html#products"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Products</a >Products</a
> >
</li> </li>
<li> <li>
<a <a
href="projects.html" href="index.html#projects-button"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Projects</a >Projects</a
> >
</li> </li>
<li> <li>
<a <a
href="clients.html" href="index.html#clients"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Clients</a >Clients</a
> >
</li> </li>
<li> <li>
<a <a
href="about.html" href="index.html#about"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>About</a >About</a
> >
</li> </li>
<li> <li>
<a <a
href="contact.html" href="contact.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Contact</a >Contact</a
> >
</li> </li>
<li> <li>
<a <a
href="blog.html" href="blog.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Blog</a >Blog</a
> >
</li> </li>
<li> <li>
<a <a
href="quote.html" href="quote.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Quote</a >Quote</a
> >
</li> </li>
@ -214,7 +226,7 @@
<!-- Contact Form --> <!-- Contact Form -->
<div class="bg-white p-8 rounded-lg shadow-sm"> <div class="bg-white p-8 rounded-lg shadow-sm">
<form class="space-y-6"> <form id="contact-form" class="space-y-6">
<!-- Name --> <!-- Name -->
<div> <div>
<label <label
@ -224,8 +236,11 @@
</label> </label>
<input <input
type="text" type="text"
placeholder="Abc" id="contact-name"
name="name"
placeholder="First name last name"
class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold" class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold"
required
/> />
</div> </div>
@ -238,8 +253,11 @@
</label> </label>
<input <input
type="email" type="email"
placeholder="Abc@def.com" id="contact-email"
name="email"
placeholder="your@email.com"
class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold" class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold"
required
/> />
</div> </div>
@ -252,8 +270,11 @@
</label> </label>
<input <input
type="text" type="text"
placeholder="This is an optional" id="contact-subject"
name="subject"
placeholder="Title of your message"
class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold" class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold"
required
/> />
</div> </div>
@ -266,14 +287,36 @@
</label> </label>
<textarea <textarea
rows="5" rows="5"
placeholder="Hi! I'd like to ask about" id="contact-message"
name="message"
placeholder="Type your message here ..."
class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold resize-none" class="w-full px-4 py-3 font-playfair font-normal text-base text-gray-500 bg-white border border-gray-300 rounded-lg focus:outline-none focus:border-uc-gold resize-none"
required
></textarea> ></textarea>
</div> </div>
<!-- Success Message -->
<div
id="contact-success"
class="hidden bg-green-50 border border-green-200 text-green-800 px-4 py-3 rounded-lg font-playfair font-normal text-base mb-4"
style="display: none"
>
Thank you for your message! We will reply to you shortly.
</div>
<!-- Error Message -->
<div
id="contact-error"
class="hidden bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded-lg font-playfair font-normal text-base mb-4"
style="display: none"
>
Please fill in all required fields before submitting.
</div>
<!-- Submit Button --> <!-- Submit Button -->
<button <button
type="submit" type="submit"
id="contact-submit"
class="bg-uc-gold text-white font-playfair font-normal text-base px-8 py-3 rounded-lg hover:bg-opacity-90 transition-all" class="bg-uc-gold text-white font-playfair font-normal text-base px-8 py-3 rounded-lg hover:bg-opacity-90 transition-all"
> >
Submit Submit
@ -519,5 +562,166 @@
</footer> </footer>
<script src="scripts/main.js"></script> <script src="scripts/main.js"></script>
<script>
// Contact form validation and submission
document.addEventListener("DOMContentLoaded", function () {
const contactForm = document.getElementById("contact-form");
const successMessage = document.getElementById("contact-success");
const errorMessage = document.getElementById("contact-error");
const submitButton = document.getElementById("contact-submit");
if (contactForm) {
contactForm.addEventListener("submit", function (e) {
e.preventDefault();
// Get form fields
const name = document.getElementById("contact-name").value.trim();
const email = document.getElementById("contact-email").value.trim();
const subject = document
.getElementById("contact-subject")
.value.trim();
const message = document
.getElementById("contact-message")
.value.trim();
// Hide any existing messages
successMessage.classList.add("hidden");
errorMessage.classList.add("hidden");
// Validate all fields
if (!name || !email || !subject || !message) {
// Show error message
errorMessage.classList.remove("hidden");
errorMessage.style.display = "block";
// Highlight empty fields with red border
const fields = [name, email, subject, message];
const fieldIds = [
"contact-name",
"contact-email",
"contact-subject",
"contact-message",
];
fieldIds.forEach((fieldId, index) => {
const field = document.getElementById(fieldId);
if (!fields[index]) {
field.classList.add("border-red-500");
field.classList.remove("border-gray-300");
} else {
field.classList.remove("border-red-500");
field.classList.add("border-gray-300");
}
});
// Scroll to error message
errorMessage.scrollIntoView({
behavior: "smooth",
block: "center",
});
// Hide error message after 3 seconds
setTimeout(() => {
errorMessage.classList.add("hidden");
errorMessage.style.display = "none";
}, 3000);
return;
}
// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
errorMessage.textContent = "Please enter a valid email address.";
errorMessage.classList.remove("hidden");
errorMessage.style.display = "block";
document
.getElementById("contact-email")
.classList.add("border-red-500");
document
.getElementById("contact-email")
.classList.remove("border-gray-300");
// Hide error message after 3 seconds
setTimeout(() => {
errorMessage.classList.add("hidden");
errorMessage.style.display = "none";
}, 3000);
return;
}
// All validation passed - show success message
successMessage.classList.remove("hidden");
successMessage.style.display = "block";
// Reset form
contactForm.reset();
// Reset all field borders
const allFields = [
"contact-name",
"contact-email",
"contact-subject",
"contact-message",
];
allFields.forEach((fieldId) => {
const field = document.getElementById(fieldId);
field.classList.remove("border-red-500");
field.classList.add("border-gray-300");
});
// Scroll to success message
successMessage.scrollIntoView({
behavior: "smooth",
block: "center",
});
// Hide success message after 3 seconds
setTimeout(() => {
successMessage.classList.add("hidden");
successMessage.style.display = "none";
}, 3000);
// Optional: Disable submit button temporarily
submitButton.disabled = true;
submitButton.textContent = "Message Sent!";
submitButton.classList.add("bg-green-600");
submitButton.classList.remove("bg-uc-gold");
// Re-enable button after 3 seconds
setTimeout(() => {
submitButton.disabled = false;
submitButton.textContent = "Submit";
submitButton.classList.remove("bg-green-600");
submitButton.classList.add("bg-uc-gold");
}, 3000);
});
// Real-time validation feedback
const formFields = [
"contact-name",
"contact-email",
"contact-subject",
"contact-message",
];
formFields.forEach((fieldId) => {
const field = document.getElementById(fieldId);
if (field) {
field.addEventListener("input", function () {
// Remove error styling when user starts typing
this.classList.remove("border-red-500");
this.classList.add("border-gray-300");
// Hide error message when user starts correcting
if (this.value.trim()) {
errorMessage.classList.add("hidden");
}
});
}
});
}
});
</script>
</body> </body>
</html> </html>

View file

@ -17,6 +17,90 @@
background-color: currentColor; background-color: currentColor;
display: inline-block; display: inline-block;
} }
/* Enhanced hover effects for curated cards */
.curated-card {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
will-change: transform;
}
.curated-card:hover .curated-card-image {
transform: scale(1.08) translateY(-12px);
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.curated-card-image {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
will-change: transform;
}
.curated-card img {
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.curated-card:hover img {
transform: scale(1.15);
}
.curated-card-title {
transition: color 0.3s ease;
}
.curated-card:hover .curated-card-title {
color: #b8873f;
}
/* Smooth scrolling for the entire page */
html {
scroll-behavior: smooth;
}
/* Active navigation link styling */
.nav-link.active {
color: #b8873f !important;
font-weight: 500;
}
/* Product card hover effects */
.product-card {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
will-change: transform;
cursor: pointer;
}
.product-card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);
}
.product-card-image {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
}
.product-card:hover .product-card-image img {
transform: scale(1.1);
}
.product-card-image img {
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.product-card-title {
transition: color 0.3s ease;
}
.product-card:hover .product-card-title {
color: #b8873f;
}
.product-card-description {
transition: color 0.3s ease;
}
.product-card:hover .product-card-description {
color: #666;
}
</style> </style>
<link <link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Playfair+Display:wght@100;200;300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Playfair+Display:wght@100;200;300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap"
@ -44,35 +128,35 @@
<li> <li>
<a <a
href="index.html" href="index.html"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Home</a >Home</a
> >
</li> </li>
<li> <li>
<a <a
href="products.html" href="#products"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Products</a >Products</a
> >
</li> </li>
<li> <li>
<a <a
href="projects.html" href="#projects-button"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Projects</a >Projects</a
> >
</li> </li>
<li> <li>
<a <a
href="clients.html" href="#clients"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>Clients</a >Clients</a
> >
</li> </li>
<li> <li>
<a <a
href="about.html" href="#about"
class="text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default" class="nav-link text-black hover:text-gray-600 font-playfair text-md font-extralight tracking-wider transition-colors text-shadow-default"
>About</a >About</a
> >
</li> </li>
@ -177,9 +261,9 @@
<!-- Image Cards --> <!-- Image Cards -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-6xl mx-auto"> <div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-6xl mx-auto">
<!-- Lounge Areas Card --> <!-- Lounge Areas Card -->
<div class="text-center"> <div class="text-center cursor-pointer curated-card">
<div <div
class="bg-black rounded-lg overflow-hidden mb-8 w-full max-w-sm h-96 md:h-[484px] mx-auto" class="curated-card-image bg-black rounded-lg overflow-hidden mb-8 w-full max-w-sm h-96 md:h-[484px] mx-auto"
> >
<img <img
src="assets/images/google_accra.jpg" src="assets/images/google_accra.jpg"
@ -188,16 +272,16 @@
/> />
</div> </div>
<h3 <h3
class="font-playfair font-semibold text-2xl leading-tight text-gray-800" class="font-playfair font-semibold text-2xl leading-tight text-gray-800 curated-card-title"
> >
Lounge Areas Lounge Areas
</h3> </h3>
</div> </div>
<!-- Workstations Card --> <!-- Workstations Card -->
<div class="text-center"> <div class="text-center cursor-pointer curated-card">
<div <div
class="bg-gray-100 rounded-lg overflow-hidden mb-8 w-full max-w-sm h-96 md:h-[484px] mx-auto" class="curated-card-image bg-gray-100 rounded-lg overflow-hidden mb-8 w-full max-w-sm h-96 md:h-[484px] mx-auto"
> >
<img <img
src="assets/images/workstation.jpg" src="assets/images/workstation.jpg"
@ -206,16 +290,16 @@
/> />
</div> </div>
<h3 <h3
class="font-playfair font-semibold text-2xl leading-tight text-gray-800" class="font-playfair font-semibold text-2xl leading-tight text-gray-800 curated-card-title"
> >
Workstations Workstations
</h3> </h3>
</div> </div>
<!-- Conference Rooms Card --> <!-- Conference Rooms Card -->
<div class="text-center"> <div class="text-center cursor-pointer curated-card">
<div <div
class="bg-blue-50 rounded-lg overflow-hidden mb-8 w-full max-w-sm h-96 md:h-[484px] mx-auto" class="curated-card-image bg-blue-50 rounded-lg overflow-hidden mb-8 w-full max-w-sm h-96 md:h-[484px] mx-auto"
> >
<img <img
src="assets/images/conference_room.jpg" src="assets/images/conference_room.jpg"
@ -224,7 +308,7 @@
/> />
</div> </div>
<h3 <h3
class="font-playfair font-semibold text-2xl leading-tight text-gray-800" class="font-playfair font-semibold text-2xl leading-tight text-gray-800 curated-card-title"
> >
Conference Rooms Conference Rooms
</h3> </h3>
@ -234,7 +318,7 @@
</section> </section>
<!-- Our Story Section --> <!-- Our Story Section -->
<section class="relative bg-white pt-8 pb-16"> <section id="about" class="relative bg-white pt-8 pb-16">
<div class="max-w-7xl mx-auto px-5"> <div class="max-w-7xl mx-auto px-5">
<!-- Section Header --> <!-- Section Header -->
<div class="text-center mb-16"> <div class="text-center mb-16">
@ -256,11 +340,12 @@
/> />
<!-- Navigation Arrow --> <!-- Navigation Arrow -->
<div class="absolute top-1/2 right-4 transform -translate-y-1/2"> <div class="absolute top-1/2 right-4 transform -translate-y-1/2">
<div <button
class="bg-white rounded-full w-12 h-12 flex items-center justify-center shadow-lg" id="story-arrow-button"
class="bg-white rounded-full w-12 h-12 flex items-center justify-center shadow-lg hover:bg-uc-gold hover:shadow-xl hover:scale-110 transition-all duration-300 cursor-pointer group"
> >
<svg <svg
class="w-6 h-6" class="w-6 h-6 transition-all duration-300 group-hover:stroke-white group-hover:scale-110"
fill="none" fill="none"
stroke="currentColor" stroke="currentColor"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@ -272,7 +357,7 @@
d="M9 5l7 7-7 7" d="M9 5l7 7-7 7"
></path> ></path>
</svg> </svg>
</div> </button>
</div> </div>
</div> </div>
@ -298,6 +383,7 @@
</p> </p>
<button <button
id="projects-button"
class="bg-black bg-opacity-70 text-white font-playfair font-normal text-xl md:text-2xl lg:text-3xl leading-tight tracking-wider px-8 py-4 rounded-lg hover:bg-opacity-80 transition-all text-center max-w-sm" class="bg-black bg-opacity-70 text-white font-playfair font-normal text-xl md:text-2xl lg:text-3xl leading-tight tracking-wider px-8 py-4 rounded-lg hover:bg-opacity-80 transition-all text-center max-w-sm"
> >
Explore past projects Explore past projects
@ -323,7 +409,7 @@
</section> </section>
<!-- Our Products Section --> <!-- Our Products Section -->
<section class="relative bg-white pt-12 pb-20"> <section id="products" class="relative bg-white pt-12 pb-20">
<div class="max-w-7xl mx-auto px-5"> <div class="max-w-7xl mx-auto px-5">
<!-- Section Header --> <!-- Section Header -->
<div class="text-center mb-16"> <div class="text-center mb-16">
@ -345,8 +431,10 @@
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12"
> >
<!-- Product Card 1: Lounge Chairs --> <!-- Product Card 1: Lounge Chairs -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/lounge_chair.jpg" src="assets/images/lounge_chair.jpg"
alt="Lounge Chairs" alt="Lounge Chairs"
@ -355,19 +443,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Lounge Chairs Lounge Chairs
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Stylish cafe chair Stylish cafe chair
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 2: Office Chairs --> <!-- Product Card 2: Office Chairs -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/office_chair.jpg" src="assets/images/office_chair.jpg"
alt="Office Chairs" alt="Office Chairs"
@ -376,19 +468,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Office Chairs Office Chairs
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Luxury big sofa Luxury big sofa
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 3: Conference Room --> <!-- Product Card 3: Conference Room -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/conference_rooms.jpg" src="assets/images/conference_rooms.jpg"
alt="Conference Room" alt="Conference Room"
@ -397,19 +493,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Conference Room Conference Room
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Tables Tables
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 4: Storage --> <!-- Product Card 4: Storage -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/storage.jpg" src="assets/images/storage.jpg"
alt="Storage" alt="Storage"
@ -418,19 +518,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Storage Storage
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Outdoor bar table and stool Outdoor bar table and stool
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 5: Kitchen --> <!-- Product Card 5: Kitchen -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/kitchen.jpg" src="assets/images/kitchen.jpg"
alt="Kitchen" alt="Kitchen"
@ -439,19 +543,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Kitchen Kitchen
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Night lamp Night lamp
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 6: Chairs --> <!-- Product Card 6: Chairs -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/chairs.jpg" src="assets/images/chairs.jpg"
alt="Chairs" alt="Chairs"
@ -460,19 +568,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Chairs Chairs
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Small mug Small mug
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 7: Pods --> <!-- Product Card 7: Pods -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/pods.jpg" src="assets/images/pods.jpg"
alt="Pods" alt="Pods"
@ -481,19 +593,23 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Pods Pods
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Cute bed set Cute bed set
</p> </p>
</div> </div>
</div> </div>
<!-- Product Card 8: Potty --> <!-- Product Card 8: Potty -->
<div class="bg-light-bg rounded-lg overflow-hidden h-[446px]"> <div
<div class="h-[301px] bg-gray-200"> class="product-card bg-light-bg rounded-lg overflow-hidden h-[446px]"
>
<div class="product-card-image h-[301px] bg-gray-200">
<img <img
src="assets/images/potty.jpg" src="assets/images/potty.jpg"
alt="Potty" alt="Potty"
@ -502,11 +618,13 @@
</div> </div>
<div class="p-4 h-[145px] flex flex-col justify-center"> <div class="p-4 h-[145px] flex flex-col justify-center">
<h3 <h3
class="font-poppins font-semibold text-xl text-gray-800 mb-2" class="product-card-title font-poppins font-semibold text-xl text-gray-800 mb-2"
> >
Potty Potty
</h3> </h3>
<p class="font-poppins font-medium text-sm text-gray-500"> <p
class="product-card-description font-poppins font-medium text-sm text-gray-500"
>
Minimalist flower pot Minimalist flower pot
</p> </p>
</div> </div>
@ -633,7 +751,7 @@
</section> </section>
<!-- Trusted by Leading Brands Section --> <!-- Trusted by Leading Brands Section -->
<section class="relative bg-floral-white py-12"> <section id="clients" class="relative bg-floral-white py-12">
<div class="max-w-7xl mx-auto px-5"> <div class="max-w-7xl mx-auto px-5">
<div class="text-center"> <div class="text-center">
<!-- Section Title --> <!-- Section Title -->
@ -703,27 +821,35 @@
<div class="max-w-7xl mx-auto px-5 py-16"> <div class="max-w-7xl mx-auto px-5 py-16">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<!-- Company Information --> <!-- Company Information -->
<div class="space-y-2"> <div class="space-y-1">
<!-- Logo --> <!-- Logo -->
<div class="w-16 h-20"> <div class="w-16 h-20 -mt-6">
<a
href="index.html"
aria-label="Go to KHY home"
title="KHY Home"
class="inline-block w-full h-full group focus:outline-none focus-visible:ring-2 focus-visible:ring-uc-gold rounded-md transition"
>
<img <img
src="assets/images/khy_logo.png" src="assets/images/khy_logo.png"
alt="khy" alt="KHY logo"
class="w-full h-full object-contain" loading="lazy"
class="w-full h-full object-contain transition-transform duration-300 group-hover:scale-105"
/> />
</a>
</div> </div>
<!-- Address --> <!-- Address -->
<p <p
class="font-playfair font-normal text-base leading-relaxed text-gray-600" class="font-playfair font-normal text-base leading-relaxed text-gray-600 -mt-4"
> >
5 Labone Crescent, Greater Accra, Ghana 5 Labone Crescent, Greater Accra, Ghana
</p> </p>
<!-- Contact Info --> <!-- Contact Info -->
<div class="space-y-1"> <div class="space-y-1 -mt-2">
<!-- Phone --> <!-- Phone -->
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3 -mt-1">
<img <img
src="assets/images/phone.png" src="assets/images/phone.png"
alt="Phone" alt="Phone"
@ -735,7 +861,7 @@
</div> </div>
<!-- Email --> <!-- Email -->
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3 -mt-1">
<img src="assets/images/mail.png" alt="Email" class="w-4 h-4" /> <img src="assets/images/mail.png" alt="Email" class="w-4 h-4" />
<span class="font-playfair font-normal text-base text-gray-800"> <span class="font-playfair font-normal text-base text-gray-800">
design@khyltd.com design@khyltd.com

View file

@ -1,8 +1,366 @@
// Update year in footer // Update year in footer and handle smooth scrolling
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
// Update footer year
const footer = document.querySelector("footer p"); const footer = document.querySelector("footer p");
if (footer) { if (footer) {
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
footer.innerHTML = footer.innerHTML.replace("2024", currentYear); footer.innerHTML = footer.innerHTML.replace("2024", currentYear);
} }
// Smooth scrolling for navigation links
const navLinks = document.querySelectorAll('.nav-link[href^="#"]');
navLinks.forEach((link) => {
link.addEventListener("click", function (e) {
e.preventDefault();
const targetId = this.getAttribute("href").substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
// Calculate offset for header height (112px = 28 * 4)
const headerHeight = 112;
const targetPosition = targetElement.offsetTop - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: "smooth",
});
}
});
});
// Handle cross-page navigation links (links that point to other pages with anchors)
const crossPageLinks = document.querySelectorAll('.nav-link[href*=".html#"]');
crossPageLinks.forEach((link) => {
link.addEventListener("click", function (e) {
// Don't prevent default - let the browser handle the navigation
// The smooth scrolling will work on the target page
});
});
// Highlight current page link
const currentPage = window.location.pathname.split("/").pop() || "index.html";
const currentPageLink = document.querySelector(
`.nav-link[href="${currentPage}"]`
);
if (currentPageLink) {
currentPageLink.classList.add("active");
}
// Active link highlighting on scroll
const sections = document.querySelectorAll("section[id]");
const navItems = document.querySelectorAll('.nav-link[href^="#"]');
function updateActiveLink() {
const scrollPosition = window.scrollY + 150; // Offset for better detection
sections.forEach((section) => {
const sectionTop = section.offsetTop;
const sectionHeight = section.offsetHeight;
const sectionId = section.getAttribute("id");
if (
scrollPosition >= sectionTop &&
scrollPosition < sectionTop + sectionHeight
) {
// Remove active class from all nav links
navItems.forEach((item) => item.classList.remove("active"));
// Add active class to corresponding nav link
const activeLink = document.querySelector(
`.nav-link[href="#${sectionId}"]`
);
if (activeLink) {
activeLink.classList.add("active");
}
}
});
}
// Listen for scroll events
window.addEventListener("scroll", updateActiveLink);
// Initial call to set active link on page load
updateActiveLink();
// Blog search functionality (only runs on blog page)
const blogSearchInput = document.getElementById("blog-search-input");
if (blogSearchInput) {
const pagination = document.getElementById("blog-pagination");
const pageButtons = document.querySelectorAll(
"#blog-pagination .blog-page-btn"
);
const nextButton = document.getElementById("blog-next-btn");
const tagButtons = document.querySelectorAll(".tag-filter");
let activeTag = ""; // empty = no tag filter
let currentPage = 1;
const pageSize = 4; // number of posts per page
function normalize(text) {
return (text || "")
.toLowerCase()
.replace(/[^a-z0-9]+/g, " ")
.trim();
}
function getFilteredArticles() {
const articles = Array.from(
document.querySelectorAll("#main-blog-content article")
);
// Sort by date descending if data-date is present (YYYY-MM-DD)
articles.sort((a, b) => {
const ad = a.getAttribute("data-date") || "";
const bd = b.getAttribute("data-date") || "";
// Fallback: keep original order if dates missing
if (!ad && !bd) return 0;
return bd.localeCompare(ad);
});
const query = normalize(blogSearchInput.value.trim());
return articles.filter((article) => {
const title = article.querySelector("h2")?.textContent || "";
const excerpt = article.querySelector("p")?.textContent || "";
const haystack = normalize(`${title} ${excerpt}`);
const tagList = (article.getAttribute("data-tags") || "")
.split(",")
.map((t) => normalize(t));
const matchesQuery = query === "" || haystack.includes(query);
const matchesTag = activeTag === "" || tagList.includes(activeTag);
return matchesQuery && matchesTag;
});
}
function renderPage() {
const filtered = getFilteredArticles();
const total = filtered.length;
const totalPages = Math.max(1, Math.ceil(total / pageSize));
currentPage = Math.min(Math.max(1, currentPage), totalPages);
// Show only items for current page
const start = (currentPage - 1) * pageSize;
const end = start + pageSize;
const toShow = new Set(filtered.slice(start, end));
document.querySelectorAll("#main-blog-content article").forEach((a) => {
a.style.display = toShow.has(a) ? "" : "none";
});
// Update pagination visibility and active state
if (pagination) {
const hasQuery = blogSearchInput.value.trim().length > 0;
pagination.style.display = hasQuery ? "none" : "flex";
pageButtons.forEach((btn) => {
const p = Number(btn.getAttribute("data-page"));
btn.classList.toggle("bg-uc-gold", p === currentPage);
btn.classList.toggle("text-white", p === currentPage);
btn.classList.toggle("bg-linen", p !== currentPage);
btn.classList.toggle("text-black", p !== currentPage);
btn.style.display = p <= totalPages ? "inline-flex" : "none";
});
if (nextButton) {
nextButton.style.display = totalPages > 1 ? "inline-flex" : "none";
nextButton.disabled = currentPage >= totalPages;
}
}
}
function filterPosts() {
// Reset to first page when filters change
currentPage = 1;
renderPage();
}
blogSearchInput.addEventListener("input", filterPosts);
// Tag filtering
tagButtons.forEach((btn) => {
btn.addEventListener("click", () => {
const clickedTag = normalize(btn.getAttribute("data-tag"));
// Toggle logic: clicking active tag clears it
activeTag = activeTag === clickedTag ? "" : clickedTag;
// Visual active state
tagButtons.forEach((b) => {
b.classList.remove("border-uc-gold", "bg-gray-50", "text-uc-gold");
b.setAttribute("aria-pressed", "false");
});
if (activeTag) {
btn.classList.add("border-uc-gold", "bg-gray-50", "text-uc-gold");
btn.setAttribute("aria-pressed", "true");
}
filterPosts();
});
});
// Pagination handlers
pageButtons.forEach((btn) =>
btn.addEventListener("click", () => {
currentPage = Number(btn.getAttribute("data-page")) || 1;
renderPage();
})
);
if (nextButton) {
nextButton.addEventListener("click", () => {
currentPage += 1;
renderPage();
});
}
// Ensure correct initial state on load
renderPage();
}
// Inline "Read more" expansion for blog posts
const articlesForExcerpt = document.querySelectorAll(
"#main-blog-content article"
);
function truncateToWords(text, maxWords) {
const words = (text || "").trim().split(/\s+/);
if (words.length <= maxWords) return { text, truncated: false };
return { text: words.slice(0, maxWords).join(" ") + "…", truncated: true };
}
articlesForExcerpt.forEach((article) => {
const excerptP = article.querySelector("p");
const readMoreBtn = article.querySelector(".read-more-toggle");
if (!excerptP || !readMoreBtn) return;
const fullExcerpt = excerptP.textContent || "";
const { text: truncated, truncated: isTruncated } = truncateToWords(
fullExcerpt,
80
);
if (isTruncated) {
// Store full text and show truncated preview
excerptP.dataset.excerptFull = fullExcerpt;
excerptP.textContent = truncated;
readMoreBtn.style.display = "inline-block";
} else {
// Nothing to expand; hide the control
readMoreBtn.style.display = "none";
}
// Click to expand (delegated fallback added below as well)
readMoreBtn.addEventListener("click", (ev) => {
ev.preventDefault();
if (excerptP.dataset.excerptFull) {
excerptP.textContent = excerptP.dataset.excerptFull;
delete excerptP.dataset.excerptFull;
}
const fullBlock = article.querySelector(".full-content");
if (fullBlock) fullBlock.classList.remove("hidden");
readMoreBtn.style.display = "none";
});
});
// Safety net: delegated handler in case markup changes
document.addEventListener("click", (e) => {
const trigger = e.target.closest(".read-more-toggle");
if (!trigger) return;
e.preventDefault();
const article = trigger.closest("article");
if (!article) return;
const excerptP = article.querySelector("p");
if (excerptP?.dataset?.excerptFull) {
excerptP.textContent = excerptP.dataset.excerptFull;
delete excerptP.dataset.excerptFull;
}
const fullBlock = article.querySelector(".full-content");
if (fullBlock) fullBlock.classList.remove("hidden");
trigger.style.display = "none";
});
// Footer newsletter subscribe validation and feedback (works on all pages)
const siteFooter = document.querySelector("footer");
if (siteFooter) {
const emailInputs = siteFooter.querySelectorAll('input[type="email"]');
emailInputs.forEach((emailInput) => {
const inputRow = emailInput.closest(".flex") || emailInput.parentElement;
let subscribeButton = inputRow ? inputRow.querySelector("button") : null;
if (!subscribeButton) {
subscribeButton = emailInput.parentElement?.querySelector("button");
}
if (!subscribeButton) return;
// Ensure non-submitting behavior
subscribeButton.type = "button";
// Create or reuse feedback element right after the row
let feedback = inputRow ? inputRow.nextElementSibling : null;
if (!(feedback instanceof HTMLElement) || !feedback.dataset.feedback) {
feedback = document.createElement("div");
feedback.dataset.feedback = "newsletter";
if (inputRow && inputRow.parentElement) {
inputRow.parentElement.insertBefore(feedback, inputRow.nextSibling);
}
}
feedback.className =
"hidden mt-3 rounded-lg px-4 py-3 font-playfair text-base";
function showMessage(text, type) {
feedback.textContent = text;
feedback.className =
"mt-3 rounded-lg px-4 py-3 font-playfair text-base";
if (type === "success") {
feedback.classList.add(
"bg-green-50",
"border",
"border-green-200",
"text-green-800"
);
} else {
feedback.classList.add(
"bg-red-50",
"border",
"border-red-200",
"text-red-800"
);
}
feedback.classList.remove("hidden");
setTimeout(() => feedback.classList.add("hidden"), 3000);
}
subscribeButton.addEventListener("click", (e) => {
e.preventDefault();
const value = (emailInput.value || "").trim();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// Reset error styles
emailInput.classList.remove("border-red-500");
if (!emailRegex.test(value)) {
emailInput.classList.add("border-red-500");
showMessage("Please enter a valid email address.", "error");
emailInput.focus();
return;
}
showMessage("Thank you for subscribing!", "success");
emailInput.value = "";
subscribeButton.disabled = true;
setTimeout(() => (subscribeButton.disabled = false), 1200);
});
});
}
// Story arrow button functionality
const storyArrowButton = document.getElementById("story-arrow-button");
if (storyArrowButton) {
storyArrowButton.addEventListener("click", function () {
// You can customize this action - for now, let's scroll to the products section
const productsSection = document.getElementById("products");
if (productsSection) {
const headerHeight = 112;
const targetPosition = productsSection.offsetTop - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: "smooth",
});
}
});
}
}); });

View file

@ -598,6 +598,10 @@ video {
z-index: 50; z-index: 50;
} }
.col-span-2 {
grid-column: span 2 / span 2;
}
.mx-auto { .mx-auto {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@ -651,6 +655,50 @@ video {
margin-top: 0.25rem; margin-top: 0.25rem;
} }
.mt-4 {
margin-top: 1rem;
}
.mb-3 {
margin-bottom: 0.75rem;
}
.mt-8 {
margin-top: 2rem;
}
.mt-2 {
margin-top: 0.5rem;
}
.mt-6 {
margin-top: 1.5rem;
}
.mt-3 {
margin-top: 0.75rem;
}
.-mt-6 {
margin-top: -1.5rem;
}
.-mt-4 {
margin-top: -1rem;
}
.-mt-1 {
margin-top: -0.25rem;
}
.-mt-3 {
margin-top: -0.75rem;
}
.-mt-5 {
margin-top: -1.25rem;
}
.block { .block {
display: block; display: block;
} }
@ -663,6 +711,10 @@ video {
display: flex; display: flex;
} }
.inline-flex {
display: inline-flex;
}
.table { .table {
display: table; display: table;
} }
@ -671,6 +723,10 @@ video {
display: grid; display: grid;
} }
.hidden {
display: none;
}
.h-12 { .h-12 {
height: 3rem; height: 3rem;
} }
@ -795,6 +851,22 @@ video {
width: 1.25rem; width: 1.25rem;
} }
.w-32 {
width: 8rem;
}
.w-\[140px\] {
width: 140px;
}
.w-\[200px\] {
width: 200px;
}
.w-\[240px\] {
width: 240px;
}
.max-w-4xl { .max-w-4xl {
max-width: 56rem; max-width: 56rem;
} }
@ -845,6 +917,10 @@ video {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
} }
.cursor-pointer {
cursor: pointer;
}
.resize-none { .resize-none {
resize: none; resize: none;
} }
@ -967,6 +1043,18 @@ video {
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
} }
.space-x-6 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1.5rem * var(--tw-space-x-reverse));
margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-y-0 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0px * var(--tw-space-y-reverse));
}
.overflow-hidden { .overflow-hidden {
overflow: hidden; overflow: hidden;
} }
@ -987,6 +1075,14 @@ video {
border-radius: 0.75rem; border-radius: 0.75rem;
} }
.rounded {
border-radius: 0.25rem;
}
.rounded-md {
border-radius: 0.375rem;
}
.border { .border {
border-width: 1px; border-width: 1px;
} }
@ -1019,6 +1115,26 @@ video {
border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
} }
.border-green-200 {
--tw-border-opacity: 1;
border-color: rgb(187 247 208 / var(--tw-border-opacity, 1));
}
.border-red-200 {
--tw-border-opacity: 1;
border-color: rgb(254 202 202 / var(--tw-border-opacity, 1));
}
.border-red-500 {
--tw-border-opacity: 1;
border-color: rgb(239 68 68 / var(--tw-border-opacity, 1));
}
.border-gray-200 {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
}
.border-opacity-20 { .border-opacity-20 {
--tw-border-opacity: 0.2; --tw-border-opacity: 0.2;
} }
@ -1077,6 +1193,36 @@ video {
background-color: rgb(184 135 63 / var(--tw-bg-opacity, 1)); background-color: rgb(184 135 63 / var(--tw-bg-opacity, 1));
} }
.bg-green-50 {
--tw-bg-opacity: 1;
background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1));
}
.bg-red-50 {
--tw-bg-opacity: 1;
background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));
}
.bg-green-600 {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
}
.bg-blue-400 {
--tw-bg-opacity: 1;
background-color: rgb(96 165 250 / var(--tw-bg-opacity, 1));
}
.bg-blue-600 {
--tw-bg-opacity: 1;
background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));
}
.bg-gray-800 {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.bg-opacity-70 { .bg-opacity-70 {
--tw-bg-opacity: 0.7; --tw-bg-opacity: 0.7;
} }
@ -1117,6 +1263,14 @@ video {
padding: 1.5rem; padding: 1.5rem;
} }
.p-2 {
padding: 0.5rem;
}
.p-3 {
padding: 0.75rem;
}
.px-5 { .px-5 {
padding-left: 1.25rem; padding-left: 1.25rem;
padding-right: 1.25rem; padding-right: 1.25rem;
@ -1167,6 +1321,16 @@ video {
padding-right: 1rem; padding-right: 1rem;
} }
.px-12 {
padding-left: 3rem;
padding-right: 3rem;
}
.px-16 {
padding-left: 4rem;
padding-right: 4rem;
}
.pb-16 { .pb-16 {
padding-bottom: 4rem; padding-bottom: 4rem;
} }
@ -1195,6 +1359,14 @@ video {
padding-right: 3rem; padding-right: 3rem;
} }
.pt-6 {
padding-top: 1.5rem;
}
.text-left {
text-align: left;
}
.text-center { .text-center {
text-align: center; text-align: center;
} }
@ -1358,6 +1530,21 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity, 1)); color: rgb(255 255 255 / var(--tw-text-opacity, 1));
} }
.text-green-800 {
--tw-text-opacity: 1;
color: rgb(22 101 52 / var(--tw-text-opacity, 1));
}
.text-red-800 {
--tw-text-opacity: 1;
color: rgb(153 27 27 / var(--tw-text-opacity, 1));
}
.text-gray-400 {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.text-opacity-90 { .text-opacity-90 {
--tw-text-opacity: 0.9; --tw-text-opacity: 0.9;
} }
@ -1415,16 +1602,79 @@ video {
transition-duration: 150ms; transition-duration: 150ms;
} }
.transition-transform {
transition-property: transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-300 {
transition-duration: 300ms;
}
.ease-in-out {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.hover\:scale-110:hover {
--tw-scale-x: 1.1;
--tw-scale-y: 1.1;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.hover\:border-gray-600:hover { .hover\:border-gray-600:hover {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-border-opacity, 1)); border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));
} }
.hover\:border-uc-gold:hover {
--tw-border-opacity: 1;
border-color: rgb(184 135 63 / var(--tw-border-opacity, 1));
}
.hover\:bg-uc-gold:hover { .hover\:bg-uc-gold:hover {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(184 135 63 / var(--tw-bg-opacity, 1)); background-color: rgb(184 135 63 / var(--tw-bg-opacity, 1));
} }
.hover\:bg-gray-100:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-50:hover {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.hover\:bg-blue-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
}
.hover\:bg-blue-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-900:hover {
--tw-bg-opacity: 1;
background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));
}
.hover\:bg-green-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1));
}
.hover\:bg-opacity-80:hover { .hover\:bg-opacity-80:hover {
--tw-bg-opacity: 0.8; --tw-bg-opacity: 0.8;
} }
@ -1448,6 +1698,17 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity, 1)); color: rgb(255 255 255 / var(--tw-text-opacity, 1));
} }
.hover\:text-uc-gold:hover {
--tw-text-opacity: 1;
color: rgb(184 135 63 / var(--tw-text-opacity, 1));
}
.hover\:shadow-xl:hover {
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.focus\:border-black:focus { .focus\:border-black:focus {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(0 0 0 / var(--tw-border-opacity, 1)); border-color: rgb(0 0 0 / var(--tw-border-opacity, 1));
@ -1463,6 +1724,49 @@ video {
outline-offset: 2px; outline-offset: 2px;
} }
.focus-visible\:ring-2:focus-visible {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus-visible\:ring-uc-gold:focus-visible {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(184 135 63 / var(--tw-ring-opacity, 1));
}
.group:hover .group-hover\:-translate-y-2 {
--tw-translate-y: -0.5rem;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group:hover .group-hover\:scale-105 {
--tw-scale-x: 1.05;
--tw-scale-y: 1.05;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group:hover .group-hover\:scale-110 {
--tw-scale-x: 1.1;
--tw-scale-y: 1.1;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group:hover .group-hover\:stroke-white {
stroke: #FFFFFF;
}
.group:hover .group-hover\:text-uc-gold {
--tw-text-opacity: 1;
color: rgb(184 135 63 / var(--tw-text-opacity, 1));
}
.group:hover .group-hover\:shadow-2xl {
--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
@media (min-width: 768px) { @media (min-width: 768px) {
.md\:top-\[24rem\] { .md\:top-\[24rem\] {
top: 24rem; top: 24rem;