commit 28f618fc4d6bdd3a9c79eb7ce05f4c918b288b8f Author: support Date: Wed Feb 11 19:37:15 2026 +0000 Clean initial commit diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..d3c86b1 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,31 @@ +kind: pipeline +type: docker +name: deploy + +steps: + - name: build + image: node:18-alpine + volumes: + - name: website-data + path: /host-target + commands: + - npm ci || npm install + - npm run build + - cp -a . /host-target + - chmod -R 777 /host-target + + - name: sync-files + image: alpine:latest + volumes: + - name: website-data + path: /host-target + commands: + - ls -la /host-target + - ls -la /host-target/assets/images/ + - ls -la /host-target/assets/icons/ + - echo "Deployment completed successfully" + +volumes: + - name: website-data + host: + path: /root/kh3website/data/html diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17197ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +dist/ +build/ +*.min.css +*.min.js +styles/main.css + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ + +# Temporary folders +tmp/ +temp/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe44ee3 --- /dev/null +++ b/README.md @@ -0,0 +1,130 @@ +# KH3 Website + +A clean, minimal static website built with HTML, JavaScript, and Tailwind CSS for KH3 - Building Inspiring Spaces. + +## Quick Start + +### Prerequisites + +- Node.js (for Tailwind CSS CLI) +- npm (comes with Node.js) + +### Setup Instructions + +1. **Clone or download the project** + + ```bash + git clone + cd kh3_website + ``` + +2. **Install Tailwind CSS** + + ```bash + npm install + ``` + +3. **Generate the optimized CSS** + + ```bash + npm run build + ``` + +4. **Open the website** + - Open `index.html` in your web browser + - Or serve it with a local server + +## Project Structure + +``` +kh3_website/ +├─ index.html # Main website page +├─ about.html # About Us page +├─ contact.html # Contact page +├─ src/ +│ └─ input.css # Tailwind directives +├─ styles/ +│ └─ main.css # Generated optimized CSS +├─ js/ +│ └─ main.js # JavaScript functionality +├─ assets/images/ # Image assets +├─ tailwind.config.js # Tailwind configuration +├─ package.json # Dependencies +└─ README.md # This file +``` + +## Development + +### For Active Development + +If you're making frequent changes to the HTML, you can use watch mode to automatically regenerate CSS: + +```bash +npm run watch +``` + +Keep this running in a terminal while you work. It will automatically rebuild the CSS whenever you save changes to your HTML files. + +### Manual Regeneration + +If watch mode doesn't work or you prefer manual control: + +```bash +# One-time build +npm run build + +# Watch mode (auto-regenerate on changes) +npm run watch +``` + +**Note:** If watch mode doesn't work, just run the one-time build command after each change. + +### What This Does + +- Scans your HTML files for used Tailwind classes +- Generates only the CSS you need (purges unused styles) +- Creates a tiny, optimized CSS file (~1KB vs ~3MB CDN) + +## Features + +- **Clean, minimal design** with Tailwind CSS +- **Optimized performance** with purged CSS +- **Responsive layout** that works on all devices +- **No build tools required** for production +- **Easy maintenance** with Tailwind utility classes +- **Custom animations** for logo, menu grid, and buttons +- **Auto-switching hero images with slide+zoom transitions** +- **Staggered loading animations** +- **Enhanced page transitions** +- **Letter-by-letter menu animations** + +To add new Tailwind classes: + +1. Add the classes to your HTML +2. Run the CSS generation command +3. The new styles will be included in the output + +To modify the design: + +1. Change Tailwind classes in HTML files +2. Regenerate CSS with the CLI command +3. Refresh your browser to see changes + +## Custom Colors & Animations + +The website uses custom KH3 brand colors and animations defined in `tailwind.config.js`: + +- **Colors**: kh3-black, kh3-red, kh3-gold, kh3-darkGold, kh3-lightGold +- **Animations**: logo-float, text-float, border-glow, menu-grid-cycle, fade-in variants + +## Production + +For production deployment: + +1. Run `npm run build` to generate the final CSS +2. Upload all files to your web server +3. The website will work without Node.js in production + +## License + +MIT License diff --git a/about.html b/about.html new file mode 100644 index 0000000..d4eb04f --- /dev/null +++ b/about.html @@ -0,0 +1,423 @@ + + + + + + + Why - KH3 + + + + + + + + + + + + + + + + +
+ + KH3 + +
+ + +
+ +
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

WHY

+
+
+
+
+
+ About KH3 + +
+
+
+ + + +
+
+
+
+

KH3 is Ghana's leading + Construction Project Management Firm with a focus on Interior Design and Fit-out. Founded in + 2014 by a highly motivated team, KH3 is + committed to being the standard of business excellence in Africa.

+

Our turnkey approach provides + our clients with a single point of contact. This liberates them to refocus on their core + business. Results: Exceptional projects completed within budget and on time!

+

Our forward thinking, highly + sort after network of professionals, artisans, suppliers and subcontractors, makeup the + power house that is the KH3 team.

+

Guided by our core values of + Beauty, Integrity, Loyalty, Diligence, Excellence, Resilience and Studiousness, our team has + executed over 20,000 square meters of office space for international and national brands + such as Google, Align, DBG and Enterprise Group Limited.

+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 01 +
+

+ VISION

+
+
+

+ We will be the standard of global business excellence in Africa.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 02 +
+

+ MISSION

+
+
+

+ Out of the ordinary the Extraordinary that inspires the world.

+
+
+
+
+
+
+ + + +
+
+
+

+ VALUES +

+
+ + +
+ + +
+
    + +
+
+ + +
+ +
+ +
+
+
+ + +
+ + + +
+ +
+
+

+ Let's Build Something Inspiring Together +

+

+ Ready to start your next project? We're here to turn your vision into a stunning reality. +

+ + Get In Touch + +
+
+ + +
+
+
+ + +
+ + KH3 Logo + +

+ Building inspiring spaces through innovative construction and design solutions since 2014. +

+
+ + +
+

Navigate

+ +
+ + +
+

Connect

+ + +
+ + +
+
+ + +
+

Location

+

29 Labone Crescent, Accra, Ghana

+
+ +
+
+ +
+
+

© KH3 Group. All Rights Reserved.

+
+
+
+
+ + + + +
+ + +
+
+ + KH3 + +
+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/assets/icons/closed_petal.png b/assets/icons/closed_petal.png new file mode 100644 index 0000000..8f198f6 Binary files /dev/null and b/assets/icons/closed_petal.png differ diff --git a/assets/icons/open_petal.png b/assets/icons/open_petal.png new file mode 100644 index 0000000..fa3858f Binary files /dev/null and b/assets/icons/open_petal.png differ diff --git a/assets/images/chair.png b/assets/images/chair.png new file mode 100644 index 0000000..c7a49c4 Binary files /dev/null and b/assets/images/chair.png differ diff --git a/assets/images/chair.webp b/assets/images/chair.webp new file mode 100644 index 0000000..70328f8 Binary files /dev/null and b/assets/images/chair.webp differ diff --git a/assets/images/contact.png b/assets/images/contact.png new file mode 100644 index 0000000..c9b0e1c Binary files /dev/null and b/assets/images/contact.png differ diff --git a/assets/images/contact.webp b/assets/images/contact.webp new file mode 100644 index 0000000..9cfff80 Binary files /dev/null and b/assets/images/contact.webp differ diff --git a/assets/images/google.png b/assets/images/google.png new file mode 100644 index 0000000..e14cb13 Binary files /dev/null and b/assets/images/google.png differ diff --git a/assets/images/google.webp b/assets/images/google.webp new file mode 100644 index 0000000..620c760 Binary files /dev/null and b/assets/images/google.webp differ diff --git a/assets/images/kh3_logo.png b/assets/images/kh3_logo.png new file mode 100644 index 0000000..f5ce2ba Binary files /dev/null and b/assets/images/kh3_logo.png differ diff --git a/assets/images/kh3_logo.webp b/assets/images/kh3_logo.webp new file mode 100644 index 0000000..6f3d4dd Binary files /dev/null and b/assets/images/kh3_logo.webp differ diff --git a/assets/images/kh3_logo1.png b/assets/images/kh3_logo1.png new file mode 100644 index 0000000..4207181 Binary files /dev/null and b/assets/images/kh3_logo1.png differ diff --git a/assets/images/kh3_logo1.webp b/assets/images/kh3_logo1.webp new file mode 100644 index 0000000..30d80ea Binary files /dev/null and b/assets/images/kh3_logo1.webp differ diff --git a/assets/images/kh3_logo2.png b/assets/images/kh3_logo2.png new file mode 100644 index 0000000..f499e7e Binary files /dev/null and b/assets/images/kh3_logo2.png differ diff --git a/assets/images/kh3_logo2.webp b/assets/images/kh3_logo2.webp new file mode 100644 index 0000000..73e6ed6 Binary files /dev/null and b/assets/images/kh3_logo2.webp differ diff --git a/assets/images/kh3_logo_darkk.png b/assets/images/kh3_logo_darkk.png new file mode 100644 index 0000000..afd730e Binary files /dev/null and b/assets/images/kh3_logo_darkk.png differ diff --git a/assets/images/kh3_logo_darkk.webp b/assets/images/kh3_logo_darkk.webp new file mode 100644 index 0000000..867ec1d Binary files /dev/null and b/assets/images/kh3_logo_darkk.webp differ diff --git a/assets/images/projects/proj-001/master-001.webp b/assets/images/projects/proj-001/master-001.webp new file mode 100644 index 0000000..bb4553c Binary files /dev/null and b/assets/images/projects/proj-001/master-001.webp differ diff --git a/assets/images/projects/proj-001/master-002.webp b/assets/images/projects/proj-001/master-002.webp new file mode 100644 index 0000000..c0a4986 Binary files /dev/null and b/assets/images/projects/proj-001/master-002.webp differ diff --git a/assets/images/projects/proj-001/master-003.webp b/assets/images/projects/proj-001/master-003.webp new file mode 100644 index 0000000..d8f1b9c Binary files /dev/null and b/assets/images/projects/proj-001/master-003.webp differ diff --git a/assets/images/projects/proj-001/master-004.webp b/assets/images/projects/proj-001/master-004.webp new file mode 100644 index 0000000..29d653f Binary files /dev/null and b/assets/images/projects/proj-001/master-004.webp differ diff --git a/assets/images/projects/proj-001/master-005.webp b/assets/images/projects/proj-001/master-005.webp new file mode 100644 index 0000000..1086264 Binary files /dev/null and b/assets/images/projects/proj-001/master-005.webp differ diff --git a/assets/images/projects/proj-001/master-006.webp b/assets/images/projects/proj-001/master-006.webp new file mode 100644 index 0000000..93a5402 Binary files /dev/null and b/assets/images/projects/proj-001/master-006.webp differ diff --git a/assets/images/projects/proj-001/master-007.webp b/assets/images/projects/proj-001/master-007.webp new file mode 100644 index 0000000..3d17ec2 Binary files /dev/null and b/assets/images/projects/proj-001/master-007.webp differ diff --git a/assets/images/projects/proj-001/master-008.webp b/assets/images/projects/proj-001/master-008.webp new file mode 100644 index 0000000..dc79f18 Binary files /dev/null and b/assets/images/projects/proj-001/master-008.webp differ diff --git a/assets/images/projects/proj-001/master-009.webp b/assets/images/projects/proj-001/master-009.webp new file mode 100644 index 0000000..8472b65 Binary files /dev/null and b/assets/images/projects/proj-001/master-009.webp differ diff --git a/assets/images/projects/proj-001/master-010.webp b/assets/images/projects/proj-001/master-010.webp new file mode 100644 index 0000000..348915f Binary files /dev/null and b/assets/images/projects/proj-001/master-010.webp differ diff --git a/assets/images/projects/proj-001/master-011.webp b/assets/images/projects/proj-001/master-011.webp new file mode 100644 index 0000000..442e30e Binary files /dev/null and b/assets/images/projects/proj-001/master-011.webp differ diff --git a/assets/images/projects/proj-001/master-012.webp b/assets/images/projects/proj-001/master-012.webp new file mode 100644 index 0000000..fb0c805 Binary files /dev/null and b/assets/images/projects/proj-001/master-012.webp differ diff --git a/assets/images/projects/proj-002/align-001.webp b/assets/images/projects/proj-002/align-001.webp new file mode 100644 index 0000000..9d2fc1c Binary files /dev/null and b/assets/images/projects/proj-002/align-001.webp differ diff --git a/assets/images/projects/proj-002/align-002.webp b/assets/images/projects/proj-002/align-002.webp new file mode 100644 index 0000000..4f66371 Binary files /dev/null and b/assets/images/projects/proj-002/align-002.webp differ diff --git a/assets/images/projects/proj-002/align-003.webp b/assets/images/projects/proj-002/align-003.webp new file mode 100644 index 0000000..f25363a Binary files /dev/null and b/assets/images/projects/proj-002/align-003.webp differ diff --git a/assets/images/projects/proj-002/align-004.webp b/assets/images/projects/proj-002/align-004.webp new file mode 100644 index 0000000..49a7d23 Binary files /dev/null and b/assets/images/projects/proj-002/align-004.webp differ diff --git a/assets/images/projects/proj-002/align-005.webp b/assets/images/projects/proj-002/align-005.webp new file mode 100644 index 0000000..ad73516 Binary files /dev/null and b/assets/images/projects/proj-002/align-005.webp differ diff --git a/assets/images/projects/proj-002/align-006.webp b/assets/images/projects/proj-002/align-006.webp new file mode 100644 index 0000000..3672696 Binary files /dev/null and b/assets/images/projects/proj-002/align-006.webp differ diff --git a/assets/images/projects/proj-002/align-007.webp b/assets/images/projects/proj-002/align-007.webp new file mode 100644 index 0000000..1aa3bdc Binary files /dev/null and b/assets/images/projects/proj-002/align-007.webp differ diff --git a/assets/images/projects/proj-002/align-008.webp b/assets/images/projects/proj-002/align-008.webp new file mode 100644 index 0000000..819fb06 Binary files /dev/null and b/assets/images/projects/proj-002/align-008.webp differ diff --git a/assets/images/projects/proj-003/calbank-001.webp b/assets/images/projects/proj-003/calbank-001.webp new file mode 100644 index 0000000..6d81f7f Binary files /dev/null and b/assets/images/projects/proj-003/calbank-001.webp differ diff --git a/assets/images/projects/proj-003/calbank-002.webp b/assets/images/projects/proj-003/calbank-002.webp new file mode 100644 index 0000000..f012f83 Binary files /dev/null and b/assets/images/projects/proj-003/calbank-002.webp differ diff --git a/assets/images/projects/proj-003/calbank-003.webp b/assets/images/projects/proj-003/calbank-003.webp new file mode 100644 index 0000000..f7c1b37 Binary files /dev/null and b/assets/images/projects/proj-003/calbank-003.webp differ diff --git a/assets/images/projects/proj-003/calbank-004.webp b/assets/images/projects/proj-003/calbank-004.webp new file mode 100644 index 0000000..2248933 Binary files /dev/null and b/assets/images/projects/proj-003/calbank-004.webp differ diff --git a/assets/images/projects/proj-003/calbank-005.webp b/assets/images/projects/proj-003/calbank-005.webp new file mode 100644 index 0000000..225baa9 Binary files /dev/null and b/assets/images/projects/proj-003/calbank-005.webp differ diff --git a/assets/images/projects/proj-003/calbank-006.webp b/assets/images/projects/proj-003/calbank-006.webp new file mode 100644 index 0000000..917a5f4 Binary files /dev/null and b/assets/images/projects/proj-003/calbank-006.webp differ diff --git a/assets/images/projects/proj-003/calbank-007.webp b/assets/images/projects/proj-003/calbank-007.webp new file mode 100644 index 0000000..8ba6efb Binary files /dev/null and b/assets/images/projects/proj-003/calbank-007.webp differ diff --git a/assets/images/projects/proj-003/calbank-008.webp b/assets/images/projects/proj-003/calbank-008.webp new file mode 100644 index 0000000..e70ccec Binary files /dev/null and b/assets/images/projects/proj-003/calbank-008.webp differ diff --git a/assets/images/projects/proj-004/google-001.jpg b/assets/images/projects/proj-004/google-001.jpg new file mode 100644 index 0000000..c249939 Binary files /dev/null and b/assets/images/projects/proj-004/google-001.jpg differ diff --git a/assets/images/projects/proj-004/google-002.jpg b/assets/images/projects/proj-004/google-002.jpg new file mode 100644 index 0000000..e4bbb79 Binary files /dev/null and b/assets/images/projects/proj-004/google-002.jpg differ diff --git a/assets/images/projects/proj-004/google-003.jpg b/assets/images/projects/proj-004/google-003.jpg new file mode 100644 index 0000000..16b4faa Binary files /dev/null and b/assets/images/projects/proj-004/google-003.jpg differ diff --git a/assets/images/projects/proj-004/google-004.jpg b/assets/images/projects/proj-004/google-004.jpg new file mode 100644 index 0000000..9407454 Binary files /dev/null and b/assets/images/projects/proj-004/google-004.jpg differ diff --git a/assets/images/projects/proj-004/google-005.jpg b/assets/images/projects/proj-004/google-005.jpg new file mode 100644 index 0000000..475a936 Binary files /dev/null and b/assets/images/projects/proj-004/google-005.jpg differ diff --git a/assets/images/projects/proj-004/google-006.jpg b/assets/images/projects/proj-004/google-006.jpg new file mode 100644 index 0000000..364b491 Binary files /dev/null and b/assets/images/projects/proj-004/google-006.jpg differ diff --git a/assets/images/projects/proj-004/google-007.jpg b/assets/images/projects/proj-004/google-007.jpg new file mode 100644 index 0000000..5921639 Binary files /dev/null and b/assets/images/projects/proj-004/google-007.jpg differ diff --git a/assets/images/projects/proj-004/google-008.webp b/assets/images/projects/proj-004/google-008.webp new file mode 100644 index 0000000..5dee394 Binary files /dev/null and b/assets/images/projects/proj-004/google-008.webp differ diff --git a/assets/images/projects/proj-004/google-009.webp b/assets/images/projects/proj-004/google-009.webp new file mode 100644 index 0000000..38ed55a Binary files /dev/null and b/assets/images/projects/proj-004/google-009.webp differ diff --git a/assets/images/projects/proj-004/google-010.jpg b/assets/images/projects/proj-004/google-010.jpg new file mode 100644 index 0000000..09baa4d Binary files /dev/null and b/assets/images/projects/proj-004/google-010.jpg differ diff --git a/assets/images/projects/proj-004/google-011.webp b/assets/images/projects/proj-004/google-011.webp new file mode 100644 index 0000000..419e2af Binary files /dev/null and b/assets/images/projects/proj-004/google-011.webp differ diff --git a/assets/images/projects/proj-005/norfund-001.webp b/assets/images/projects/proj-005/norfund-001.webp new file mode 100644 index 0000000..fa72e51 Binary files /dev/null and b/assets/images/projects/proj-005/norfund-001.webp differ diff --git a/assets/images/projects/proj-005/norfund-002.webp b/assets/images/projects/proj-005/norfund-002.webp new file mode 100644 index 0000000..c878e1e Binary files /dev/null and b/assets/images/projects/proj-005/norfund-002.webp differ diff --git a/assets/images/projects/proj-005/norfund-003.webp b/assets/images/projects/proj-005/norfund-003.webp new file mode 100644 index 0000000..d43ea93 Binary files /dev/null and b/assets/images/projects/proj-005/norfund-003.webp differ diff --git a/assets/images/projects/proj-005/norfund-004.webp b/assets/images/projects/proj-005/norfund-004.webp new file mode 100644 index 0000000..c3b0e18 Binary files /dev/null and b/assets/images/projects/proj-005/norfund-004.webp differ diff --git a/assets/images/projects/proj-005/norfund-005.webp b/assets/images/projects/proj-005/norfund-005.webp new file mode 100644 index 0000000..a68bfd4 Binary files /dev/null and b/assets/images/projects/proj-005/norfund-005.webp differ diff --git a/assets/images/projects/proj-005/norfund-006.webp b/assets/images/projects/proj-005/norfund-006.webp new file mode 100644 index 0000000..55b1fbe Binary files /dev/null and b/assets/images/projects/proj-005/norfund-006.webp differ diff --git a/assets/images/projects/proj-005/norfund-007.webp b/assets/images/projects/proj-005/norfund-007.webp new file mode 100644 index 0000000..2ad680f Binary files /dev/null and b/assets/images/projects/proj-005/norfund-007.webp differ diff --git a/assets/images/projects/proj-005/norfund-008.webp b/assets/images/projects/proj-005/norfund-008.webp new file mode 100644 index 0000000..691483c Binary files /dev/null and b/assets/images/projects/proj-005/norfund-008.webp differ diff --git a/assets/images/projects/proj-006/devbank-001.webp b/assets/images/projects/proj-006/devbank-001.webp new file mode 100644 index 0000000..a94abcf Binary files /dev/null and b/assets/images/projects/proj-006/devbank-001.webp differ diff --git a/assets/images/projects/proj-006/devbank-002.webp b/assets/images/projects/proj-006/devbank-002.webp new file mode 100644 index 0000000..5bb2536 Binary files /dev/null and b/assets/images/projects/proj-006/devbank-002.webp differ diff --git a/assets/images/projects/proj-006/devbank-003.webp b/assets/images/projects/proj-006/devbank-003.webp new file mode 100644 index 0000000..202787c Binary files /dev/null and b/assets/images/projects/proj-006/devbank-003.webp differ diff --git a/assets/images/projects/proj-006/devbank-004.webp b/assets/images/projects/proj-006/devbank-004.webp new file mode 100644 index 0000000..973a02c Binary files /dev/null and b/assets/images/projects/proj-006/devbank-004.webp differ diff --git a/assets/images/projects/proj-006/devbank-006.webp b/assets/images/projects/proj-006/devbank-006.webp new file mode 100644 index 0000000..777aab8 Binary files /dev/null and b/assets/images/projects/proj-006/devbank-006.webp differ diff --git a/assets/images/projects/proj-006/devbank-007.webp b/assets/images/projects/proj-006/devbank-007.webp new file mode 100644 index 0000000..d63a88e Binary files /dev/null and b/assets/images/projects/proj-006/devbank-007.webp differ diff --git a/assets/images/projects/proj-006/devbank-008.webp b/assets/images/projects/proj-006/devbank-008.webp new file mode 100644 index 0000000..fa716a8 Binary files /dev/null and b/assets/images/projects/proj-006/devbank-008.webp differ diff --git a/assets/images/projects/proj-006/devbank-05.webp b/assets/images/projects/proj-006/devbank-05.webp new file mode 100644 index 0000000..10dbfe5 Binary files /dev/null and b/assets/images/projects/proj-006/devbank-05.webp differ diff --git a/assets/images/projects/proj-007/oracle-001.webp b/assets/images/projects/proj-007/oracle-001.webp new file mode 100644 index 0000000..108f8af Binary files /dev/null and b/assets/images/projects/proj-007/oracle-001.webp differ diff --git a/assets/images/projects/proj-007/oracle-002.webp b/assets/images/projects/proj-007/oracle-002.webp new file mode 100644 index 0000000..8906d6b Binary files /dev/null and b/assets/images/projects/proj-007/oracle-002.webp differ diff --git a/assets/images/projects/proj-007/oracle-003.webp b/assets/images/projects/proj-007/oracle-003.webp new file mode 100644 index 0000000..8fc869f Binary files /dev/null and b/assets/images/projects/proj-007/oracle-003.webp differ diff --git a/assets/images/projects/proj-007/oracle-004.webp b/assets/images/projects/proj-007/oracle-004.webp new file mode 100644 index 0000000..a4eb807 Binary files /dev/null and b/assets/images/projects/proj-007/oracle-004.webp differ diff --git a/assets/images/projects/proj-007/oracle-005.webp b/assets/images/projects/proj-007/oracle-005.webp new file mode 100644 index 0000000..3d93b7f Binary files /dev/null and b/assets/images/projects/proj-007/oracle-005.webp differ diff --git a/assets/images/projects/proj-007/oracle-006.webp b/assets/images/projects/proj-007/oracle-006.webp new file mode 100644 index 0000000..6ecfd42 Binary files /dev/null and b/assets/images/projects/proj-007/oracle-006.webp differ diff --git a/assets/images/projects/proj-008/elac-001.webp b/assets/images/projects/proj-008/elac-001.webp new file mode 100644 index 0000000..e2ea5dd Binary files /dev/null and b/assets/images/projects/proj-008/elac-001.webp differ diff --git a/assets/images/projects/proj-008/elac-002.webp b/assets/images/projects/proj-008/elac-002.webp new file mode 100644 index 0000000..451cc17 Binary files /dev/null and b/assets/images/projects/proj-008/elac-002.webp differ diff --git a/assets/images/projects/proj-008/elac-003.webp b/assets/images/projects/proj-008/elac-003.webp new file mode 100644 index 0000000..780dc1f Binary files /dev/null and b/assets/images/projects/proj-008/elac-003.webp differ diff --git a/assets/images/projects/proj-008/elac-004.webp b/assets/images/projects/proj-008/elac-004.webp new file mode 100644 index 0000000..226d2a7 Binary files /dev/null and b/assets/images/projects/proj-008/elac-004.webp differ diff --git a/assets/images/projects/proj-008/elac-005.webp b/assets/images/projects/proj-008/elac-005.webp new file mode 100644 index 0000000..9cfe069 Binary files /dev/null and b/assets/images/projects/proj-008/elac-005.webp differ diff --git a/assets/images/projects/proj-008/elac-006.webp b/assets/images/projects/proj-008/elac-006.webp new file mode 100644 index 0000000..8899a43 Binary files /dev/null and b/assets/images/projects/proj-008/elac-006.webp differ diff --git a/assets/images/projects/proj-008/elac-007.webp b/assets/images/projects/proj-008/elac-007.webp new file mode 100644 index 0000000..62f405c Binary files /dev/null and b/assets/images/projects/proj-008/elac-007.webp differ diff --git a/assets/images/projects/proj-009/ge-001.webp b/assets/images/projects/proj-009/ge-001.webp new file mode 100644 index 0000000..26bc612 Binary files /dev/null and b/assets/images/projects/proj-009/ge-001.webp differ diff --git a/assets/images/projects/proj-009/ge-002.webp b/assets/images/projects/proj-009/ge-002.webp new file mode 100644 index 0000000..321308e Binary files /dev/null and b/assets/images/projects/proj-009/ge-002.webp differ diff --git a/assets/images/projects/proj-009/ge-003.webp b/assets/images/projects/proj-009/ge-003.webp new file mode 100644 index 0000000..0871060 Binary files /dev/null and b/assets/images/projects/proj-009/ge-003.webp differ diff --git a/assets/images/projects/proj-009/ge-004.webp b/assets/images/projects/proj-009/ge-004.webp new file mode 100644 index 0000000..9e4adef Binary files /dev/null and b/assets/images/projects/proj-009/ge-004.webp differ diff --git a/assets/images/projects/proj-009/ge-005.webp b/assets/images/projects/proj-009/ge-005.webp new file mode 100644 index 0000000..9f58b4a Binary files /dev/null and b/assets/images/projects/proj-009/ge-005.webp differ diff --git a/assets/images/projects/proj-009/ge-006.webp b/assets/images/projects/proj-009/ge-006.webp new file mode 100644 index 0000000..fc1c229 Binary files /dev/null and b/assets/images/projects/proj-009/ge-006.webp differ diff --git a/assets/images/projects/proj-009/ge-007.webp b/assets/images/projects/proj-009/ge-007.webp new file mode 100644 index 0000000..be3d010 Binary files /dev/null and b/assets/images/projects/proj-009/ge-007.webp differ diff --git a/assets/images/projects/proj-009/ge-008.webp b/assets/images/projects/proj-009/ge-008.webp new file mode 100644 index 0000000..81c9f94 Binary files /dev/null and b/assets/images/projects/proj-009/ge-008.webp differ diff --git a/assets/images/projects/proj-009/ge-009.webp b/assets/images/projects/proj-009/ge-009.webp new file mode 100644 index 0000000..5c5d144 Binary files /dev/null and b/assets/images/projects/proj-009/ge-009.webp differ diff --git a/assets/images/projects/proj-010/8d-001.jpg b/assets/images/projects/proj-010/8d-001.jpg new file mode 100644 index 0000000..9dc6030 Binary files /dev/null and b/assets/images/projects/proj-010/8d-001.jpg differ diff --git a/assets/images/projects/proj-010/8d-002.jpg b/assets/images/projects/proj-010/8d-002.jpg new file mode 100644 index 0000000..1fe7884 Binary files /dev/null and b/assets/images/projects/proj-010/8d-002.jpg differ diff --git a/assets/images/projects/proj-010/8d-003.jpg b/assets/images/projects/proj-010/8d-003.jpg new file mode 100644 index 0000000..0447f43 Binary files /dev/null and b/assets/images/projects/proj-010/8d-003.jpg differ diff --git a/assets/images/projects/proj-010/8d-004.jpg b/assets/images/projects/proj-010/8d-004.jpg new file mode 100644 index 0000000..5bbe2e8 Binary files /dev/null and b/assets/images/projects/proj-010/8d-004.jpg differ diff --git a/assets/images/projects/proj-010/8d-005.webp b/assets/images/projects/proj-010/8d-005.webp new file mode 100644 index 0000000..d98c3ce Binary files /dev/null and b/assets/images/projects/proj-010/8d-005.webp differ diff --git a/assets/images/projects/proj-010/8d-006.webp b/assets/images/projects/proj-010/8d-006.webp new file mode 100644 index 0000000..cfbe16b Binary files /dev/null and b/assets/images/projects/proj-010/8d-006.webp differ diff --git a/assets/images/projects/proj-010/8d-007.webp b/assets/images/projects/proj-010/8d-007.webp new file mode 100644 index 0000000..c8f4c74 Binary files /dev/null and b/assets/images/projects/proj-010/8d-007.webp differ diff --git a/assets/images/projects/proj-010/8d-008.webp b/assets/images/projects/proj-010/8d-008.webp new file mode 100644 index 0000000..7e953ad Binary files /dev/null and b/assets/images/projects/proj-010/8d-008.webp differ diff --git a/assets/images/projects/proj-010/8d-009.webp b/assets/images/projects/proj-010/8d-009.webp new file mode 100644 index 0000000..cd6dde4 Binary files /dev/null and b/assets/images/projects/proj-010/8d-009.webp differ diff --git a/assets/images/projects/proj-010/8d-010.webp b/assets/images/projects/proj-010/8d-010.webp new file mode 100644 index 0000000..a75c62b Binary files /dev/null and b/assets/images/projects/proj-010/8d-010.webp differ diff --git a/assets/images/room.png b/assets/images/room.png new file mode 100644 index 0000000..5d957e9 Binary files /dev/null and b/assets/images/room.png differ diff --git a/assets/images/room.webp b/assets/images/room.webp new file mode 100644 index 0000000..0ac314e Binary files /dev/null and b/assets/images/room.webp differ diff --git a/assets/images/team/andrews.png b/assets/images/team/andrews.png new file mode 100644 index 0000000..c9df9ca Binary files /dev/null and b/assets/images/team/andrews.png differ diff --git a/assets/images/team/andrews.webp b/assets/images/team/andrews.webp new file mode 100644 index 0000000..0f4cbbf Binary files /dev/null and b/assets/images/team/andrews.webp differ diff --git a/assets/images/team/claribel.png b/assets/images/team/claribel.png new file mode 100644 index 0000000..c16bd92 Binary files /dev/null and b/assets/images/team/claribel.png differ diff --git a/assets/images/team/claribel.webp b/assets/images/team/claribel.webp new file mode 100644 index 0000000..9beb60f Binary files /dev/null and b/assets/images/team/claribel.webp differ diff --git a/assets/images/team/daniel.png b/assets/images/team/daniel.png new file mode 100644 index 0000000..e2ace18 Binary files /dev/null and b/assets/images/team/daniel.png differ diff --git a/assets/images/team/daniel.webp b/assets/images/team/daniel.webp new file mode 100644 index 0000000..3c21fe7 Binary files /dev/null and b/assets/images/team/daniel.webp differ diff --git a/assets/images/team/dorothea.png b/assets/images/team/dorothea.png new file mode 100644 index 0000000..1dd4c38 Binary files /dev/null and b/assets/images/team/dorothea.png differ diff --git a/assets/images/team/dorothea.webp b/assets/images/team/dorothea.webp new file mode 100644 index 0000000..6a87c6f Binary files /dev/null and b/assets/images/team/dorothea.webp differ diff --git a/assets/images/team/fauzia.png b/assets/images/team/fauzia.png new file mode 100644 index 0000000..e6ea8c7 Binary files /dev/null and b/assets/images/team/fauzia.png differ diff --git a/assets/images/team/fauzia.webp b/assets/images/team/fauzia.webp new file mode 100644 index 0000000..851b0f6 Binary files /dev/null and b/assets/images/team/fauzia.webp differ diff --git a/assets/images/team/female.png b/assets/images/team/female.png new file mode 100644 index 0000000..3caf75a Binary files /dev/null and b/assets/images/team/female.png differ diff --git a/assets/images/team/francis.png b/assets/images/team/francis.png new file mode 100644 index 0000000..6268ed3 Binary files /dev/null and b/assets/images/team/francis.png differ diff --git a/assets/images/team/francis.webp b/assets/images/team/francis.webp new file mode 100644 index 0000000..89b48a0 Binary files /dev/null and b/assets/images/team/francis.webp differ diff --git a/assets/images/team/google.png b/assets/images/team/google.png new file mode 100644 index 0000000..e14cb13 Binary files /dev/null and b/assets/images/team/google.png differ diff --git a/assets/images/team/google.webp b/assets/images/team/google.webp new file mode 100644 index 0000000..eca6440 Binary files /dev/null and b/assets/images/team/google.webp differ diff --git a/assets/images/team/hanetta.png b/assets/images/team/hanetta.png new file mode 100644 index 0000000..38503c6 Binary files /dev/null and b/assets/images/team/hanetta.png differ diff --git a/assets/images/team/hanetta.webp b/assets/images/team/hanetta.webp new file mode 100644 index 0000000..b41f407 Binary files /dev/null and b/assets/images/team/hanetta.webp differ diff --git a/assets/images/team/helena.png b/assets/images/team/helena.png new file mode 100644 index 0000000..4c41169 Binary files /dev/null and b/assets/images/team/helena.png differ diff --git a/assets/images/team/helena.webp b/assets/images/team/helena.webp new file mode 100644 index 0000000..fae6b6f Binary files /dev/null and b/assets/images/team/helena.webp differ diff --git a/assets/images/team/joyleen.png b/assets/images/team/joyleen.png new file mode 100644 index 0000000..16ddc59 Binary files /dev/null and b/assets/images/team/joyleen.png differ diff --git a/assets/images/team/joyleen.webp b/assets/images/team/joyleen.webp new file mode 100644 index 0000000..64c5b11 Binary files /dev/null and b/assets/images/team/joyleen.webp differ diff --git a/assets/images/team/kweku_hayford.png b/assets/images/team/kweku_hayford.png new file mode 100644 index 0000000..ee2fca2 Binary files /dev/null and b/assets/images/team/kweku_hayford.png differ diff --git a/assets/images/team/kweku_hayford.webp b/assets/images/team/kweku_hayford.webp new file mode 100644 index 0000000..f21ee8f Binary files /dev/null and b/assets/images/team/kweku_hayford.webp differ diff --git a/assets/images/team/male.png b/assets/images/team/male.png new file mode 100644 index 0000000..7ea0c03 Binary files /dev/null and b/assets/images/team/male.png differ diff --git a/assets/images/team/michael.png b/assets/images/team/michael.png new file mode 100644 index 0000000..cc253b1 Binary files /dev/null and b/assets/images/team/michael.png differ diff --git a/assets/images/team/michael.webp b/assets/images/team/michael.webp new file mode 100644 index 0000000..1ea6d00 Binary files /dev/null and b/assets/images/team/michael.webp differ diff --git a/assets/images/team/miranda.png b/assets/images/team/miranda.png new file mode 100644 index 0000000..bdb437d Binary files /dev/null and b/assets/images/team/miranda.png differ diff --git a/assets/images/team/miranda.webp b/assets/images/team/miranda.webp new file mode 100644 index 0000000..8173c93 Binary files /dev/null and b/assets/images/team/miranda.webp differ diff --git a/assets/images/team/moses.png b/assets/images/team/moses.png new file mode 100644 index 0000000..5ea2b1b Binary files /dev/null and b/assets/images/team/moses.png differ diff --git a/assets/images/team/moses.webp b/assets/images/team/moses.webp new file mode 100644 index 0000000..f64bdce Binary files /dev/null and b/assets/images/team/moses.webp differ diff --git a/assets/images/team/rebecca.png b/assets/images/team/rebecca.png new file mode 100644 index 0000000..2c9d983 Binary files /dev/null and b/assets/images/team/rebecca.png differ diff --git a/assets/images/team/rebecca.webp b/assets/images/team/rebecca.webp new file mode 100644 index 0000000..3499d46 Binary files /dev/null and b/assets/images/team/rebecca.webp differ diff --git a/assets/images/team/siisi.png b/assets/images/team/siisi.png new file mode 100644 index 0000000..37c513c Binary files /dev/null and b/assets/images/team/siisi.png differ diff --git a/assets/images/team/siisi.webp b/assets/images/team/siisi.webp new file mode 100644 index 0000000..64e163b Binary files /dev/null and b/assets/images/team/siisi.webp differ diff --git a/assets/images/team/team_photo.png b/assets/images/team/team_photo.png new file mode 100644 index 0000000..c4c5c7a Binary files /dev/null and b/assets/images/team/team_photo.png differ diff --git a/assets/images/team/team_photo.webp b/assets/images/team/team_photo.webp new file mode 100644 index 0000000..edd73ea Binary files /dev/null and b/assets/images/team/team_photo.webp differ diff --git a/assets/images/team/yayra.png b/assets/images/team/yayra.png new file mode 100644 index 0000000..372b3e0 Binary files /dev/null and b/assets/images/team/yayra.png differ diff --git a/assets/images/team/yayra.webp b/assets/images/team/yayra.webp new file mode 100644 index 0000000..2e98409 Binary files /dev/null and b/assets/images/team/yayra.webp differ diff --git a/contact copy.html b/contact copy.html new file mode 100644 index 0000000..82bd351 --- /dev/null +++ b/contact copy.html @@ -0,0 +1,182 @@ + + + + + + Contact Us - KH3 | Building Inspiring Spaces + + + + + + + + + + + + +
KH3
+ + +
+ +
+ + +
+
+
+ Office Background +
+
+
+
+ + +
+

Get In Touch

+

Ready to start your next project? We'd love to hear from you. Fill out the form and we'll get back to you within 24 hours.

+
+
+ 📍 +

Address

29 Labone Crescent, Accra, Ghana

+
+
+ 📞 +

Phone

+233 30 396 9970

+
+
+ ✉️ +

Email

Info@KH3group.com

+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+

Find Us

+
+ +
+
+
+
+ + +
+ +
+
+

+ Let's Build Something Inspiring Together +

+

+ Ready to start your next project? We're here to turn your vision into a stunning reality. +

+ + Get In Touch + +
+
+ + +
+
+
+ + +
+ + KH3 Logo + +

+ Building inspiring spaces through innovative construction and design solutions since 2014. +

+
+ + +
+

Navigate

+ +
+ + +
+

Connect

+ + +
+ + +
+
+ + +
+

Location

+

29 Labone Crescent, Accra, Ghana

+
+ +
+
+ +
+
+

© KH3 Group. All Rights Reserved.

+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/contact.html b/contact.html new file mode 100644 index 0000000..4f29140 --- /dev/null +++ b/contact.html @@ -0,0 +1,318 @@ + + + + + + + Contact Us - KH3 | Building Inspiring Spaces + + + + + + + + + + + + + + + +
+ + KH3 + +
+ + +
+ +
+ + +
+
+
+ Office Background +
+
+
+
+ + +
+

Get In Touch

+

Ready to start your next project? We'd love to hear from you. Fill out + the form and we'll get back to you within 24 hours.

+
+
+ 📍 +
+

Address

+

29 Labone Crescent, Accra, Ghana

+
+
+
+ 📞 +
+

Phone

+

+233 30 396 9970

+
+
+
+ ✉️ +
+

Email

+

Info@KH3group.com

+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+

+ Find Us

+
+ +
+
+
+
+ + +
+ +
+
+

+ Let's Build Something Inspiring Together +

+

+ Ready to start your next project? We're here to turn your vision into a stunning reality. +

+ + Get In Touch + +
+
+ + +
+
+
+ + +
+ + KH3 Logo + +

+ Building inspiring spaces through innovative construction and design solutions since 2014. +

+
+ + +
+

Navigate

+ +
+ + +
+

Connect

+ + +
+ + +
+
+ + +
+

Location

+

29 Labone Crescent, Accra, Ghana

+
+ +
+
+ +
+
+

© KH3 Group. All Rights Reserved.

+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/data/projects.json b/data/projects.json new file mode 100644 index 0000000..fdd39ff --- /dev/null +++ b/data/projects.json @@ -0,0 +1,272 @@ +[ + { + "id": "proj-001", + "name": "Mastercard Foundation Office", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "RAZOR.KH3 acted as Design & Build Contractor for the new Mastercard Foundation office at Stanbic Heights, Airport City, Accra. Scope covered design and construction management including partitioning works, mechanical, electrical and plumbing (MEP), flooring and furniture installations.", + "client": "Mastercard Foundation", + "typeOfWork": "Design & Build; design and construction management; partitioning, MEP, flooring, furniture installations", + "size": "1,807 SQM", + "completionDate": "2024", + "images": [ + "assets/images/projects/proj-001/master-001.webp", + "assets/images/projects/proj-001/master-002.webp", + "assets/images/projects/proj-001/master-003.webp", + "assets/images/projects/proj-001/master-004.webp", + "assets/images/projects/proj-001/master-005.webp", + "assets/images/projects/proj-001/master-006.webp", + "assets/images/projects/proj-001/master-007.webp", + "assets/images/projects/proj-001/master-008.webp", + "assets/images/projects/proj-001/master-009.webp", + "assets/images/projects/proj-001/master-010.webp", + "assets/images/projects/proj-001/master-011.webp", + "assets/images/projects/proj-001/master-012.webp" + ], + "highlights": [ + "Modern open-plan design", + "Collaborative workspace zones", + "Premium materials and finishes", + "Integrated technology systems" + ] + }, + { + "id": "proj-002", + "name": "Align Technology Company Ltd", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "RAZOR.KH3 delivered the Accra office for Align Technology Company Ltd as Design & Build Contractor at the Grand Oyeeman, Airport City. Scope included design & construction management with partitioning works, mechanical, electrical & plumbing (MEP), flooring and furniture installations.", + "client": "Align Technology Company Ltd", + "typeOfWork": "Design & Build; design & construction management; partitioning, MEP, flooring, furniture installations", + "size": "200 SQM", + "completionDate": "2022", + "images": [ + "assets/images/projects/proj-002/align-001.webp", + "assets/images/projects/proj-002/align-002.webp", + "assets/images/projects/proj-002/align-003.webp", + "assets/images/projects/proj-002/align-004.webp", + "assets/images/projects/proj-002/align-005.webp", + "assets/images/projects/proj-002/align-006.webp", + "assets/images/projects/proj-002/align-007.webp", + "assets/images/projects/proj-002/align-008.webp" + ], + "highlights": [ + "Design & Build by RAZOR.KH3", + "Located at Grand Oyeeman, Airport City", + "Scope: partitioning, MEP, flooring, furniture" + ] + }, + { + "id": "proj-003", + "name": "Cal Bank Learning Centre", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "RAZOR.KH3 served as Interior Design & Build Contractor. Space optimisation Design & Build to include evaluation of existing space and design optimisation to align with client accommodation needs. Works include partitioning works, mechanical, electrical & plumbing (MEP) works, flooring and joinery installations.", + "client": "Cal Bank", + "typeOfWork": "Design & Build; space evaluation & optimisation; partitioning, MEP, flooring, joinery", + "size": "292 SQM", + "completionDate": "2022", + "images": [ + "assets/images/projects/proj-003/calbank-001.webp", + "assets/images/projects/proj-003/calbank-002.webp", + "assets/images/projects/proj-003/calbank-003.webp", + "assets/images/projects/proj-003/calbank-004.webp", + "assets/images/projects/proj-003/calbank-005.webp", + "assets/images/projects/proj-003/calbank-006.webp", + "assets/images/projects/proj-003/calbank-007.webp", + "assets/images/projects/proj-003/calbank-008.webp" + ], + "highlights": [ + "Interior design and construction", + "Partitioning, MEP, flooring", + "Furniture installations" + ] + }, + { + "id": "proj-004", + "name": "Google Accra Office Fit-out", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "RAZOR.KH3 served as General Contractor implementing the design by Boogermart & MultiCAD. Scope included partitioning works, mechanical, electrical and plumbing (MEP), flooring and joinery installations. The project was managed by Mace PTY (South Africa).", + "client": "Google", + "typeOfWork": "General contracting; partitioning, MEP, flooring, joinery installations", + "size": "925 SQM", + "completionDate": "2022", + "images": [ + "assets/images/projects/proj-004/google-001.webp", + "assets/images/projects/proj-004/google-002.webp", + "assets/images/projects/proj-004/google-003.webp", + "assets/images/projects/proj-004/google-004.webp", + "assets/images/projects/proj-004/google-005.webp", + "assets/images/projects/proj-004/google-006.webp", + "assets/images/projects/proj-004/google-007.webp", + "assets/images/projects/proj-004/google-008.webp", + "assets/images/projects/proj-004/google-009.webp", + "assets/images/projects/proj-004/google-010.webp" + ], + "highlights": [ + "RAZOR.KH3 as General Contractor", + "Design by Boogermart & MultiCAD", + "Project management by Mace PTY (South Africa)", + "Scope: partitioning, MEP, flooring, joinery" + ] + }, + { + "id": "proj-005", + "name": "Norfund West Africa", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "RAZOR.KH3 served as Design & Build Contractor for the Norfund West‑Africa office at One Airport Square, Airport City, Accra. KH3 Produkts Ltd provided supply and installation. Scope included design & construction management, partitioning works, mechanical, electrical & plumbing (MEP), flooring and furniture installations.", + "client": "Norfund West‑Africa", + "typeOfWork": "Design & Build; design & construction management; partitioning, MEP, flooring, furniture installations", + "size": "200 SQM", + "completionDate": "2022", + "images": [ + "assets/images/projects/proj-005/norfund-001.webp", + "assets/images/projects/proj-005/norfund-002.webp", + "assets/images/projects/proj-005/norfund-003.webp", + "assets/images/projects/proj-005/norfund-004.webp", + "assets/images/projects/proj-005/norfund-005.webp", + "assets/images/projects/proj-005/norfund-006.webp", + "assets/images/projects/proj-005/norfund-007.webp", + "assets/images/projects/proj-005/norfund-008.webp" + ], + "highlights": [ + "RAZOR.KH3 as Design & Build Contractor", + "KH3 Produkts Ltd as supply & installation vendor", + "Scope: partitioning, MEP, flooring, furniture" + ] + }, + { + "id": "proj-006", + "name": "Development Bank, Ghana", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "RAZOR.KH3 and rhayCAD served as Design & Build Contractors for the Development Bank Ghana office fit-out. The engagement included space evaluation and optimisation to align with accommodation needs and philosophy, followed by construction of the optimised design. Works included partitioning, mechanical, electrical & plumbing (MEP), flooring and joinery installations.", + "client": "Development Bank Ghana", + "typeOfWork": "Design & Build; space optimisation; partitioning, MEP, flooring, joinery", + "size": "973 SQM", + "completionDate": "2021", + "images": [ + "assets/images/projects/proj-006/devbank-001.webp", + "assets/images/projects/proj-006/devbank-002.webp", + "assets/images/projects/proj-006/devbank-003.webp", + "assets/images/projects/proj-006/devbank-004.webp", + "assets/images/projects/proj-006/devbank-005.webp", + "assets/images/projects/proj-006/devbank-006.webp", + "assets/images/projects/proj-006/devbank-007.webp", + "assets/images/projects/proj-006/devbank-008.webp" + ], + "highlights": [ + "Design & Build by RAZOR.KH3 and rhayCAD", + "Space optimisation to align with client needs", + "Scope: partitioning, MEP, flooring, joinery" + ] + }, + { + "id": "proj-007", + "name": "Oracle Office", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "KH3 served as Design & Build Contractor for the Oracle office fit-out. Scope included space planning and delivery of partitioning works, mechanical, electrical & plumbing (MEP), flooring and joinery installations.", + "client": "Oracle", + "typeOfWork": "Design & Build; partitioning, MEP, flooring, joinery", + "size": "130 SQM", + "completionDate": "2020", + "images": [ + "assets/images/projects/proj-007/oracle-001.webp", + "assets/images/projects/proj-007/oracle-002.webp", + "assets/images/projects/proj-007/oracle-003.webp", + "assets/images/projects/proj-007/oracle-004.webp", + "assets/images/projects/proj-007/oracle-005.webp", + "assets/images/projects/proj-007/oracle-006.webp" + ], + "highlights": [ + "Historic preservation", + "Modern hospitality fit-outs", + "Restaurant and bar renovations", + "Premium guest amenities" + ] + }, + { + "id": "proj-008", + "name": "Enterprise Group Head Office", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "KH3 and rhayCAD delivered the Enterprise Group Head Office fit‑out at Advantage Place, Ridge, Accra as Design & Build Contractors. Scope covered design and construction management including interior design, partitioning works, mechanical, electrical & plumbing (MEP), flooring and furniture installations.", + "client": "Enterprise Group", + "typeOfWork": "Design & Build; design & construction management; interior design, partitioning, MEP, flooring, furniture installations", + "size": "1,800 SQM", + "completionDate": "2019", + "images": [ + "assets/images/projects/proj-008/elac-001.webp", + "assets/images/projects/proj-008/elac-002.webp", + "assets/images/projects/proj-008/elac-003.webp", + "assets/images/projects/proj-008/elac-004.webp", + "assets/images/projects/proj-008/elac-005.webp", + "assets/images/projects/proj-008/elac-006.webp", + "assets/images/projects/proj-008/elac-007.webp" + ], + "highlights": [ + "Design & Build by KH3 and rhayCAD", + "Interior design and space partitioning", + "Scope: MEP, flooring, furniture installations" + ] + }, + { + "id": "proj-009", + "name": "General Electric Head Office Fit-out", + "category": "Corporate", + "location": "Accra, Ghana", + "description": "KH3 and rhayCAD served as General Contractors implementing the design by Paragon Interiors (South Africa) for the General Electric head office. Works included partitioning, mechanical, electrical & plumbing (MEP), flooring and joinery installations, delivered in collaboration with Lerumo PTY (South Africa) and ARG1 Africa.", + "client": "General Electric", + "typeOfWork": "General contracting; implementation of Paragon Interiors design; partitioning, MEP, flooring, joinery", + "size": "965 SQM", + "completionDate": "", + "images": [ + "assets/images/projects/proj-009/ge-001.webp", + "assets/images/projects/proj-009/ge-002.webp", + "assets/images/projects/proj-009/ge-003.webp", + "assets/images/projects/proj-009/ge-004.webp", + "assets/images/projects/proj-009/ge-005.webp", + "assets/images/projects/proj-009/ge-006.webp", + "assets/images/projects/proj-009/ge-007.webp", + "assets/images/projects/proj-009/ge-008.webp", + "assets/images/projects/proj-009/ge-009.webp" + ], + "highlights": [ + "General Contractors: KH3 & rhayCAD", + "Design by Paragon Interiors (South Africa)", + "Collaboration with Lerumo PTY and ARG1 Africa", + "Scope: partitioning, MEP, flooring, joinery" + ] + }, + { + "id": "proj-010", + "name": "8D – Accra Office Fit-Out", + "category": "Corporate", + "location": "One Airport Square, Airport, Ghana", + "description": "Interior Design & Build Contractor. Space optimisation Design & Build to include evaluation of existing space and design optimisation to align with client accommodation needs. Works include partitioning works, mechanical, electrical & plumbing (MEP) works, flooring and joinery installations. Delivered by KH3.", + "client": "8D Ghana", + "typeOfWork": "Interior Design & Build Contractor; space evaluation & optimisation; partitioning, MEP, flooring, joinery", + "size": "250 SQM", + "completionDate": "October 2018", + "images": [ + "assets/images/projects/proj-010/8d-001.jpg", + "assets/images/projects/proj-010/8d-002.jpg", + "assets/images/projects/proj-010/8d-003.jpg", + "assets/images/projects/proj-010/8d-004.jpg", + "assets/images/projects/proj-010/8d-005.webp", + "assets/images/projects/proj-010/8d-006.webp", + "assets/images/projects/proj-010/8d-007.webp", + "assets/images/projects/proj-010/8d-008.webp", + "assets/images/projects/proj-010/8d-009.webp", + "assets/images/projects/proj-010/8d-010.webp" + ], + "highlights": [ + "Design–Build Contractor", + "250 m² office fit‑out", + "Delivered at One Airport Square" + ] + } +] \ No newline at end of file diff --git a/data/team.json b/data/team.json new file mode 100644 index 0000000..6ccfa98 --- /dev/null +++ b/data/team.json @@ -0,0 +1,146 @@ +[ + { + "id": 1, + "name": [ + "Kweku", + "HAYFORD" + ], + "title": "Director", + "image": "assets/images/team/kweku_hayford.webp" + }, + { + "id": 2, + "name": [ + "Hanetta", + "HAYFORD" + ], + "title": "Managing Director, KHY", + "image": "assets/images/team/hanetta.webp" + }, + { + "id": 3, + "name": [ + "Yayra", + "NUMETU" + ], + "title": "Head, Finance & Administration", + "image": "assets/images/team/yayra.webp" + }, + { + "id": 4, + "name": [ + "Fauzia", + "CLOTTEY" + ], + "title": "Managing Director, Produkts", + "image": "assets/images/team/fauzia.webp" + }, + { + "id": 5, + "name": [ + "Miranda", + "LARYEA" + ], + "title": "Business Development Manager", + "image": "assets/images/team/miranda.webp" + }, + { + "id": 6, + "name": [ + "Helena", + "NTIRI AMANKWAH" + ], + "title": "Procurement Specialist", + "image": "assets/images/team/helena.webp" + }, + { + "id": 7, + "name": [ + "Michael", + "LARTEY" + ], + "title": "Construction Project Coordinator", + "image": "assets/images/team/michael.webp" + }, + { + "id": 8, + "name": [ + "Francis", + "OPARE" + ], + "title": "Finance Officer", + "image": "assets/images/team/francis.webp" + }, + { + "id": 9, + "name": [ + "Andrews Amon", + "KOTEY" + ], + "title": "Project Design Coordinator", + "image": "assets/images/team/andrews.webp" + }, + { + "id": 10, + "name": [ + "Dorothea", + "ADJETEY" + ], + "title": "Operations & Branding Officer", + "image": "assets/images/team/dorothea.webp" + }, + { + "id": 11, + "name": [ + "Joyleen", + "Therson-COFFIE" + ], + "title": "Assistant Project Design Coordinator", + "image": "assets/images/team/joyleen.webp" + }, + { + "id": 12, + "name": [ + "Rebecca", + "SAM" + ], + "title": "Finance Assistant", + "image": "assets/images/team/rebecca.webp" + }, + { + "id": 13, + "name": [ + "Daniel", + "THOMPSON" + ], + "title": "Assistant Project Coordinator", + "image": "assets/images/team/daniel.webp" + }, + { + "id": 14, + "name": [ + "Albert", + "ANKU" + ], + "title": "3D Visualizer and Graphic Designer", + "image": "assets/images/team/male.png" + }, + { + "id": 15, + "name": [ + "Yvan", + "YAWSON-SACKEY" + ], + "title": "Assistant Project Design Coordinator", + "image": "assets/images/team/male.png" + }, + { + "id": 16, + "name": [ + "Sitsofe Akosua", + "ASAFOH" + ], + "title": "IT Consultant", + "image": "assets/images/team/female.png" + } +] \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..e532c9d --- /dev/null +++ b/index.html @@ -0,0 +1,178 @@ + + + + + + + KH3 - Building Inspiring Spaces + + + + + + + + + + + + + +
+
+ + + + + +
+ +
+ + +
+
+ + +
+
+
+ Sample interior fit-out by KH3 + Sample interior fit-out by KH3 + + +
+
+ Why + Contacts +
+
+
+
+ + + +
+
+ + + + + +
+
+ + KH3 + +
+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/js/about.js b/js/about.js new file mode 100644 index 0000000..41964a6 --- /dev/null +++ b/js/about.js @@ -0,0 +1,60 @@ +document.addEventListener('DOMContentLoaded', function() { + + // --- Interactive Values Section Logic --- + const valuesData = [ + { title: "Beauty", description: "We treat all stake holders with politeness, dignity and civility that equals the outward beauty of our environment and the environments we create." }, + { title: "Innovation", description: "We challenge the status quo. We seek better, smarter and more beautiful ways to solve problems and deliver value. When ideas fall short, we learn, adapt and try again- never settling, always solving." }, + { title: "Loyalty", description: "We are faithful to our mission and vision and that of our stakeholders and the organizations they represent." }, + { title: "Diligence", description: "We give our utmost attention to all our projects. We do this in earnest and with precision." }, + { title: "Excellence", description: "We are committed to delivering exceptional results in every area of our operations." }, + { title: "Resilience", description: "In the face of daunting challenges, setbacks and failures; we learn and document lessons, bounce back and persist in the pursuit of goals, targets, objectives and deadlines. We do this with focused optimism." }, + { title: "Studiousness", description: "We are committed to learning and advancing our services, products, and tools to best serve our stakeholders." } + ]; + + const valuesListContainer = document.getElementById('values-list'); + const valuesContentContainer = document.getElementById('values-content'); + const valuesSection = document.getElementById('values-section'); + + if (valuesListContainer && valuesContentContainer && valuesSection) { + + // Populate the list and content blocks + valuesListContainer.innerHTML = valuesData.map((value, index) => ` +
  • + ${value.title} +
  • + `).join(''); + + valuesContentContainer.innerHTML = valuesData.map((value, index) => ` +
    + +
    0${index + 1}
    + +

    ${value.title}

    + +

    ${value.description}

    +
    + `).join(''); + + const valueItems = valuesListContainer.querySelectorAll('.value-item'); + const contentBlocks = valuesContentContainer.querySelectorAll('.value-content-block'); + + // Function to update the active state + const updateActiveValue = (index) => { + valueItems.forEach(item => item.classList.remove('active')); + contentBlocks.forEach(block => block.classList.remove('active')); + + valuesListContainer.querySelector(`.value-item[data-index='${index}']`).classList.add('active'); + valuesContentContainer.querySelector(`.value-content-block[data-index='${index}']`).classList.add('active'); + }; + + // Add hover event listeners for desktop + valueItems.forEach((item, index) => { + item.addEventListener('mouseenter', () => { + // Only trigger on hover if not a touch device (basic check) + if (window.matchMedia('(hover: hover)').matches) { + updateActiveValue(index); + } + }); + }); + } +}); \ No newline at end of file diff --git a/js/carousel.js b/js/carousel.js new file mode 100644 index 0000000..008fd1e --- /dev/null +++ b/js/carousel.js @@ -0,0 +1,84 @@ +document.addEventListener('DOMContentLoaded', () => { + // Generic function to handle the carousel logic + function initializeCarousel(currentImgEl, nextImgEl, imageArray) { + if (!currentImgEl || !nextImgEl) { + return; // If the elements aren't on this page, do nothing + } + + currentImgEl.classList.add('opacity-0'); + currentImgEl.style.animation = "fadeInRight 1s ease-out 0.3s forwards"; + + let currentIndex = 0; + let isTransitioning = false; + const slideDirections = ["left", "right"]; + let slideIndex = 0; + + function performSlideZoomTransition() { + if (isTransitioning) return; + isTransitioning = true; + const nextIndex = (currentIndex + 1) % imageArray.length; + const slideDirection = slideDirections[slideIndex % slideDirections.length]; + slideIndex++; + + nextImgEl.src = imageArray[nextIndex]; + nextImgEl.style.opacity = "1"; + + if (slideDirection === "left") { + currentImgEl.style.animation = "slideOutLeft 1s ease-in-out forwards"; + nextImgEl.style.animation = "zoomInFromRight 1s ease-in-out forwards"; + } else { + currentImgEl.style.animation = "slideOutRight 1s ease-in-out forwards"; + nextImgEl.style.animation = "zoomInFromLeft 1s ease-in-out forwards"; + } + + setTimeout(() => { + // The animation has finished. The 'nextImg' is now fully visible on top. + // The 'currentImg' is now hidden behind it, having completed its slide-out. + + // 1. Reset the OLD current image. It will become the 'next' image container for the next cycle. + // Clear its animation and explicitly hide it. + currentImgEl.style.animation = ""; + currentImgEl.style.opacity = "0"; // Force it to be hidden + + // 2. The 'next' image now becomes the 'current' image. + // We need to update its properties to be the new baseline. + nextImgEl.style.animation = ""; // Clear its 'zoomIn' animation + nextImgEl.style.opacity = "1"; // Ensure it is and stays visible + + // 3. Swap their IDs in the DOM. This is the key to the new logic. + // The element that was 'nextImg' is now officially 'currentImg'. + let tempId = currentImgEl.id; + currentImgEl.id = nextImgEl.id; + nextImgEl.id = tempId; + + // 4. Re-assign our script's variables to point to the newly ID'd elements. + currentImgEl = document.getElementById('currentImg'); + nextImgEl = document.getElementById('nextImg'); + + // 5. Update the index and state. + currentIndex = nextIndex; + isTransitioning = false; + }, 1000); + } + + // Start the transition cycle after initial page animations + setTimeout(() => { + setInterval(performSlideZoomTransition, 5000); + }, 2000); + } + + // --- Carousel Definitions --- + // IDs for the index page carousel + const indexCurrentImg = document.getElementById("currentImg"); + const indexNextImg = document.getElementById("nextImg"); + const indexImgs = ["assets/images/room.webp", "assets/images/chair.webp", "assets/images/google.webp"]; + + // IDs for the services page carousel + const servicesCurrentImg = document.getElementById("servicesCurrentImg"); + const servicesNextImg = document.getElementById("servicesNextImg"); + const servicesImgs = ["assets/images/room.webp", "assets/images/chair.webp", "assets/images/google.webp"]; + + // Initialize the carousels for any page that has the correct elements + initializeCarousel(indexCurrentImg, indexNextImg, indexImgs); + initializeCarousel(servicesCurrentImg, servicesNextImg, servicesImgs); +}); \ No newline at end of file diff --git a/js/contact.js b/js/contact.js new file mode 100644 index 0000000..72f6862 --- /dev/null +++ b/js/contact.js @@ -0,0 +1,122 @@ +// Contact page specific scripts + +// Form submission +document.addEventListener("DOMContentLoaded", () => { + const contactForm = document.getElementById("contactForm"); + if (contactForm) { + contactForm.addEventListener("submit", async (e) => { + e.preventDefault(); + + const submitButton = contactForm.querySelector('button[type="submit"]'); + const originalText = submitButton.innerHTML; + + // Show loading state + submitButton.innerHTML = "Sending..."; + submitButton.disabled = true; + + try { + const formData = new FormData(contactForm); + const name = formData.get("name"); + const email = formData.get("email"); + const phone = formData.get("phone"); + const company = formData.get("company"); + const service = formData.get("service"); + const budget = formData.get("budget"); + const message = formData.get("message"); + + // Send to Resend API + const response = await fetch("https://api.resend.com/emails", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer re_YOUR_API_KEY_HERE", // Replace with your Resend API key + }, + body: JSON.stringify({ + from: "KH3 Website ", // Replace with your verified domain + to: ["george.fleef@gmail.com"], + subject: `New contact form submission from ${name}`, + html: ` +

    New Contact Form Submission

    +

    Name: ${name}

    +

    Email: ${email}

    +

    Phone: ${phone || "Not provided"}

    +

    Company: ${company || "Not provided"}

    +

    Service Interest: ${ + service || "Not specified" + }

    +

    Budget: ${budget || "Not specified"}

    +

    Message:

    +

    ${message.replace(/\n/g, "
    ")}

    + `, + }), + }); + + if (response.ok) { + alert( + "Thank you for your message! We'll get back to you within 24 hours." + ); + contactForm.reset(); + } else { + throw new Error("Failed to send email"); + } + } catch (error) { + console.error("Error:", error); + alert( + "Sorry, there was an error sending your message. Please try again or contact us directly at george.fleef@gmail.com" + ); + } finally { + // Reset button + submitButton.innerHTML = originalText; + submitButton.disabled = false; + } + }); + } + + // Staggered entrance for hero and sections + window.addEventListener("load", () => { + const heroTitle = document.querySelector( + "section.relative h1.masked-reveal" + ); + const heroSub = document.querySelector("section.relative div.text-xl"); + if (heroTitle) { + heroTitle.style.animation = "maskReveal 900ms ease-out 150ms forwards"; + } + if (heroSub) { + heroSub.style.opacity = "0"; + heroSub.style.animation = "fadeUp 700ms ease-out 320ms forwards"; + } + + const contactSectionFade = document.querySelector("section.py-20.bg-white"); + if (contactSectionFade) { + contactSectionFade.style.opacity = "0"; + contactSectionFade.style.animation = + "fadeUp 800ms ease-out 600ms forwards"; + } + + const mapSection = document.querySelector("section.py-20.bg-kh3-black"); + if (mapSection) { + mapSection.style.opacity = "0"; + mapSection.style.animation = "fadeUp 800ms ease-out 850ms forwards"; + } + }); + + // Gentle auto-scroll like WHAT page: nudge ~1.1vh after 3s with easing + setTimeout(() => { + const startScroll = window.pageYOffset; + const targetScroll = window.innerHeight * 1.0; + const distance = targetScroll - startScroll; + const duration = 2000; + let start = null; + + function animateScroll(ts) { + if (start === null) start = ts; + const elapsed = ts - start; + const progress = Math.min(elapsed / duration, 1); + const easeOutQuart = 1 - Math.pow(1 - progress, 4); + window.scrollTo(0, startScroll + distance * easeOutQuart); + if (progress < 1) requestAnimationFrame(animateScroll); + } + + requestAnimationFrame(animateScroll); + }, 3000); +}); diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..e8f4234 --- /dev/null +++ b/js/main.js @@ -0,0 +1,169 @@ +// Main JavaScript for KH3 Website + +// This function will handle all animations defined by data-attributes in the HTML +function initDynamicAnimations() { + const animatedElements = document.querySelectorAll("[data-anim]"); + animatedElements.forEach((el) => { + const delay = el.getAttribute("data-anim-delay") || "0"; + el.style.animationDelay = `${delay}ms`; + // CORRECTED: Adds the required 'animate-' prefix for Tailwind to recognize the animation + el.classList.add(`animate-${el.getAttribute('data-anim')}`); + el.style.animationFillMode = 'forwards'; // Ensure animation state persists after it runs + }); +} + +// Navigation functionality +function initNavigation() { + const menuToggle = document.getElementById("menuToggle"); + const navMenu = document.getElementById("navMenu"); + const menuGrid = document.getElementById("menuGrid"); + const navLinks = document.querySelectorAll(".nav-link"); + + if (menuToggle && navMenu && menuGrid) { + let isMenuOpen = false; + const menuPetal = document.getElementById("menuPetal"); + const menuWrap = document.getElementById("menuWrap"); + + if (menuWrap) menuWrap.classList.remove("open"); + + menuToggle.addEventListener("click", () => { + isMenuOpen = !isMenuOpen; // Toggle the state + navMenu.classList.toggle("hidden"); + if (menuWrap) menuWrap.classList.toggle("open"); + }); + + document.addEventListener("click", (e) => { + if (isMenuOpen && !menuToggle.contains(e.target) && !navMenu.contains(e.target)) { + navMenu.classList.add("hidden"); + if (menuWrap) menuWrap.classList.remove("open"); + isMenuOpen = false; + } + }); + + navLinks.forEach((link) => { + link.addEventListener("click", () => { + navMenu.classList.add("hidden"); + if (menuWrap) menuWrap.classList.remove("open"); + isMenuOpen = false; + }); + }); + + document.addEventListener("keydown", (e) => { + if (e.key === "Escape" && isMenuOpen) { + navMenu.classList.add("hidden"); + if (menuWrap) menuWrap.classList.remove("open"); + isMenuOpen = false; + } + }); + } +} + +// Custom cursor +function initCustomCursor() { + if (window.innerWidth <= 768) return; + const cursor = document.getElementById("customCursor"); + if (!cursor) return; + + document.addEventListener("mousemove", (e) => { + cursor.style.left = e.clientX - 12 + "px"; + cursor.style.top = e.clientY - 12 + "px"; + }); +} + +// Loading screen +function initLoadingScreen() { + const loadingScreen = document.getElementById("loadingScreen"); + if (loadingScreen) { + setTimeout(() => { + loadingScreen.style.opacity = "0"; + setTimeout(() => { + loadingScreen.style.display = "none"; + }, 500); + }, 1000); + } +} + + +// --- Main Execution --- +document.addEventListener("DOMContentLoaded", function () { + initDynamicAnimations(); + initNavigation(); + initActiveNav(); + initCustomCursor(); + initLoadingScreen(); + loadTeamMembers(); // + // Add other initializations here if needed + document.getElementById('current-year').textContent = new Date().getFullYear(); +}); + +// Handle back/forward navigation cache +window.addEventListener('pageshow', function (event) { + if (event.persisted) { + // Page was loaded from cache, so we reload to ensure scripts run correctly + window.location.reload(); + } +}); + +// NEW: Function to load team members from JSON +async function loadTeamMembers() { + const container = document.getElementById('teamGridContainer'); + // Only run this function if the container exists on the current page (i.e., on who.html) + if (!container) { + return; + } + + try { + const response = await fetch('data/team.json'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const teamMembers = await response.json(); + + const teamHTML = teamMembers.map((member, index) => { + // Create the HTML for each team member card + return ` +
    +
    +
    + ${member.name.join(' ')} +
    +
    +

    + ${member.name.join('
    ')} +

    +

    + ${member.title} +

    +
    +
    +
    + `; + }).join(''); + + container.innerHTML = teamHTML; + // After adding the cards to the DOM, re-run the animation initializer to apply the staggered delays + initDynamicAnimations(); + + } catch (error) { + console.error("Could not load team members:", error); + container.innerHTML = `

    Failed to load team members. Please try again later.

    `; + } +} + +function initActiveNav() { + const currentPage = window.location.pathname.split('/').pop(); + const navLinks = document.querySelectorAll('#navMenu a'); + + navLinks.forEach(link => { + const linkPage = link.getAttribute('href').split('/').pop(); + + // Handle the index page case where the path might be empty + if (currentPage === '' && (linkPage === 'index.html' || linkPage === '')) { + link.classList.add('active'); + } + // Handle other pages + else if (linkPage !== '' && currentPage === linkPage) { + link.classList.add('active'); + } + }); +} \ No newline at end of file diff --git a/js/projects.js b/js/projects.js new file mode 100644 index 0000000..d8d584f --- /dev/null +++ b/js/projects.js @@ -0,0 +1,163 @@ +document.addEventListener('DOMContentLoaded', function () { + // --- Start of projects.js specific logic --- + + let projectsData = []; + let currentProject = null; + let currentImageIndex = 0; + + // --- Core Functions for fetching and rendering project cards --- + async function loadProjects() { + try { + const response = await fetch("data/projects.json"); + if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); + projectsData = await response.json(); + renderProjects(); + } catch (error) { + console.error("Error loading projects:", error); + const grid = document.getElementById("projectsGrid"); + if(grid) grid.innerHTML = `

    Failed to load projects.

    `; + } + } + + function renderProjects() { + const grid = document.getElementById("projectsGrid"); + if (!grid) return; + + grid.innerHTML = projectsData.map((project, index) => ` +
    +
    + ${project.name} +

    VIEW PROJECT

    +
    +
    +
    ${project.category}${project.completionDate}
    +

    ${project.name}

    +

    ${project.description}

    +
    ${project.size}${project.location}
    +
    +
    + `).join(""); + if (window.initDynamicAnimations) window.initDynamicAnimations(); + } + + // --- MODAL Functionality (Restored from original) --- + function openProjectDetails(projectId) { + const project = projectsData.find((p) => p.id === projectId); + if (!project) return; + currentProject = project; + currentImageIndex = 0; + document.getElementById("modalTitle").textContent = project.name; + document.getElementById("modalCategory").textContent = project.category; + document.getElementById("modalDescription").textContent = project.description; + document.getElementById("modalClient").textContent = project.client; + document.getElementById("modalTypeOfWork").textContent = project.typeOfWork; + document.getElementById("modalSize").textContent = project.size; + document.getElementById("modalCompletionDate").textContent = project.completionDate; + document.getElementById("modalLocation").textContent = project.location; + document.getElementById("modalHighlights").innerHTML = project.highlights.map(h => `
  • ${h}
  • `).join(""); + + setupImageCarousel(project.images); // RESTORED CALL + + const modal = document.getElementById("projectModal"); + const modalContent = document.getElementById("modalContent"); + modal.classList.remove("hidden"); + document.body.style.overflow = "hidden"; + setTimeout(() => modalContent.classList.remove("scale-95", "opacity-0"), 10); + } + + function closeModal() { + const modal = document.getElementById("projectModal"); + const modalContent = document.getElementById("modalContent"); + modalContent.classList.add("scale-95", "opacity-0"); + setTimeout(() => { + modal.classList.add("hidden"); + document.body.style.overflow = "auto"; + }, 500); + } + + // --- MODAL CAROUSEL Functionality (Restored from original) --- + function setupImageCarousel(images) { + const mainImage = document.getElementById("modalMainImage"); + const imageDots = document.getElementById("imageDots"); + const imageCounter = document.getElementById("imageCounter"); + const totalImages = document.getElementById("totalImages"); + + mainImage.src = images[0]; + mainImage.alt = currentProject.name; + totalImages.textContent = images.length; + imageDots.innerHTML = images.map((_, index) => ``).join(""); + updateImageCarousel(); // Initial call to set counter + } + + function updateImageCarousel() { + const mainImage = document.getElementById("modalMainImage"); + const imageDots = document.getElementById("imageDots"); + const imageCounter = document.getElementById("imageCounter"); + if (!mainImage || !currentProject) return; + + mainImage.style.opacity = "0"; + setTimeout(() => { + mainImage.src = currentProject.images[currentImageIndex]; + mainImage.style.opacity = "1"; + }, 250); + + imageCounter.textContent = currentImageIndex + 1; + const dots = imageDots.querySelectorAll("button"); + dots.forEach((dot, index) => { + dot.classList.toggle("bg-kh3-red", index === currentImageIndex); + dot.classList.toggle("bg-white/30", index !== currentImageIndex); + }); + } + + // --- IMAGE ENLARGEMENT Functionality (Restored from original) --- + function enlargeImage() { + if (!currentProject) return; + const enlargedImage = document.getElementById("enlargedImage"); + document.getElementById("enlargedImageCounter").textContent = currentImageIndex + 1; + document.getElementById("enlargedTotalImages").textContent = currentProject.images.length; + enlargedImage.src = currentProject.images[currentImageIndex]; + document.getElementById("imageEnlargeModal").classList.remove("hidden"); + } + + function closeEnlargeModal() { + document.getElementById("imageEnlargeModal").classList.add("hidden"); + } + + // --- Global Accessibility for onclick and keyboard events (Restored) --- + window.openProjectDetails = openProjectDetails; + window.closeModal = closeModal; + window.enlargeImage = enlargeImage; + window.goToImage = (index) => { currentImageIndex = index; updateImageCarousel(); }; + window.nextImage = () => { currentImageIndex = (currentImageIndex + 1) % currentProject.images.length; updateImageCarousel(); }; + window.prevImage = () => { currentImageIndex = (currentImageIndex === 0) ? currentProject.images.length - 1 : currentImageIndex - 1; updateImageCarousel(); }; + + // Event listeners for modal controls + document.getElementById("closeModal")?.addEventListener("click", closeModal); + document.getElementById("projectModal")?.addEventListener("click", (e) => { if (e.target.id === "projectModal") closeModal(); }); + document.getElementById("prevImage")?.addEventListener("click", window.prevImage); + document.getElementById("nextImage")?.addEventListener("click", window.nextImage); + document.getElementById("closeEnlargeModal")?.addEventListener("click", closeEnlargeModal); + document.getElementById("enlargePrevImage")?.addEventListener("click", () => { window.prevImage(); enlargeImage(); }); + document.getElementById("enlargeNextImage")?.addEventListener("click", () => { window.nextImage(); enlargeImage(); }); + document.getElementById("imageEnlargeModal")?.addEventListener("click", (e) => { if (e.target.id === "imageEnlargeModal") closeEnlargeModal(); }); + + document.addEventListener("keydown", (e) => { + const isProjectModalOpen = !document.getElementById("projectModal")?.classList.contains("hidden"); + const isEnlargeModalOpen = !document.getElementById("imageEnlargeModal")?.classList.contains("hidden"); + + if (isEnlargeModalOpen) { + if (e.key === "ArrowLeft") { window.prevImage(); enlargeImage(); } + if (e.key === "ArrowRight") { window.nextImage(); enlargeImage(); } + if (e.key === "Escape") closeEnlargeModal(); + } else if (isProjectModalOpen) { + if (e.key === "ArrowLeft") window.prevImage(); + if (e.key === "ArrowRight") window.nextImage(); + if (e.key === "Escape") closeModal(); + } + }); + + // --- Initialize Page --- + loadProjects(); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..040b8bc --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1483 @@ +{ + "name": "kh3-website", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "kh3-website", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "tailwindcss": "^3.4.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b37d2e9 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "kh3-website", + "version": "1.0.0", + "description": "KH3 - Building Inspiring Spaces", + "main": "index.html", + "scripts": { + "build": "tailwindcss -i ./src/input.css -o ./styles/main.css", + "watch": "tailwindcss -i ./src/input.css -o ./styles/main.css --watch", + "dev": "tailwindcss -i ./src/input.css -o ./styles/main.css --watch" + }, + "devDependencies": { + "tailwindcss": "^3.4.0" + }, + "keywords": [ + "construction", + "project-management", + "fit-outs", + "ghana" + ], + "author": "KH3", + "license": "MIT" +} diff --git a/projects.html b/projects.html new file mode 100644 index 0000000..d266fde --- /dev/null +++ b/projects.html @@ -0,0 +1,293 @@ + + + + + + + What - KH3 + + + + + + + + + + + + + + + +
    + + KH3 + +
    + + +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    OUR WHAT

    +
    +
    +
    +
    +
    + KH3 Projects + KH3 Projects + +
    +
    +
    + +
    +
    +
    +
    +

    Browse through our past projects

    +

    Discover the diverse portfolio of inspiring spaces we've created + across Ghana and West Africa. Each project represents our commitment to excellence, + innovation, and transforming visions into reality.

    +
    +
    +
    + +
    +
    +
    +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/services.html b/services.html new file mode 100644 index 0000000..06642ab --- /dev/null +++ b/services.html @@ -0,0 +1,351 @@ + + + + + + + How - KH3 + + + + + + + + + + + + + + + + +
    + + KH3 + +
    + + +
    + +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    OUR HOW

    +
    +
    +
    +
    +
    + KH3 Services + KH3 Services + +
    +
    +
    + + +
    + + +
    +
    + +
    +
    +

    CONSTRUCTION PROJECT + MANAGEMENT

    +
    +
    +
    +

    Construction projects can give you a headache and present numerous concerns that can keep + you up at night. Details ranging from how to assess and select consultants or + contractors to challenges with traffic impact assessments or soil tests.

    +

    At KH3, we know it is in our interest and yours, to reduce these challenges to a minimum + by providing the expertise required to complete your project successfully and on time. +

    +
    +
    + +
    +
    +
    + +
    +

    Define project objectives and scope, plan, performance requirements, standards, + participants selection, and quality control.

    +
    +
    +
    + +
    +

    Minimize wastage and maximize value via careful procurement of labor, materials and + equipment.

    +
    +
    +
    + +
    +

    Execute the designed project diligently by managing schedule, contracting and controlling + costs.

    +
    +
    +
    + +
    +

    Review materials and work processes to ensure safety and quality.

    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    + +
    +

    In-depth stakeholder interviews to understand spatial needs (dimensions, furniture, IT, + AV/telephony, etc.).

    +
    +
    +
    + +
    +

    Assist with outlining goals, budgets, and timelines for commercial spaces.

    +
    +
    +
    + +
    +

    Identify and present suitable real estate options.

    +
    +
    +
    + +
    +

    Design and fit-out from layout to furniture selection within budget and realistic + timelines.

    +
    +
    +
    + +
    +

    Ensure highest value through safe and ethical procurement and construction methods.

    +
    +
    + +
    +
    +

    COMMERCIAL FIT-OUTS & + REFURBISHMENTS

    +
    +
    +
    +

    Acquiring commercial retail and office space requires efficient and effective + coordination. This includes identifying spatial needs, sourcing real estate, and + designing and constructing the space in line with your corporate values and brand.

    +

    KH3 manages these processes for you with an integrated system, assembling goal-focused + creative teams to meet your needs.

    +
    +
    +
    +
    + + +
    +
    + +
    +
    +

    PROGRAM MANAGEMENT

    +
    +
    +
    +

    Managing a group of related projects in a coordinated manner yields economies of scale, + implements standards, establishes a corporate look-and-feel, and delivers flexibility + and efficiencies.

    +

    Our roll-out process reduces inefficiencies, delivers flexibility, reduces cost and sets + your organization apart. We help identify, group, and implement a Program Management + Strategy that works for your organization.

    +
    +
    + +
    +
    +
    + +
    +

    Determining the nature of related projects and the value of grouping them through a + detailed interview process.

    +
    +
    +
    + +
    +

    Developing a detailed Program that identifies all projects, establishes scope, + performance standards, and controls.

    +
    +
    +
    + +
    +

    Building test models and evaluating the process and end product for fitness of purpose. +

    +
    +
    +
    + +
    +

    Refining the process and rolling out projects in adherence to Program and Project + Management Principles.

    +
    +
    +
    +
    +
    +
    + +
    + +
    + + + + + + + \ No newline at end of file diff --git a/src/input.css b/src/input.css new file mode 100644 index 0000000..4884f5a --- /dev/null +++ b/src/input.css @@ -0,0 +1,335 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@keyframes projectOverlaySlide { + from { + transform: translateY(100%); + opacity: 0; + } + + to { + transform: translateY(0); + opacity: 1; + } +} + +/* + These are component styles. Wrapping them in @layer components + is a good practice for organization with Tailwind. +*/ +@layer components { + .project-overlay { + /* The default hidden state */ + transform: translateY(100%); + opacity: 0; + /* Add a transition for a smooth exit if the mouse leaves quickly */ + transition: opacity 0.3s ease; + } + + .project-card:hover .project-overlay { + /* On hover, run the slide-in animation */ + animation: projectOverlaySlide 0.4s ease-out forwards; + } + + .project-card .project-image { + /* Add a transition for the zoom effect */ + transition: transform 0.6s ease-out; + } + + .project-card:hover .project-image { + /* On hover, zoom the image */ + transform: scale(1.1); + } +} + +@layer components { + + /* Reusable Component for Navigation Links */ + .nav-link { + @apply block text-white text-xl md:text-lg font-medium hover:text-kh3-red transition-colors font-montserrat opacity-0; + } + + .nav-link.active { + @apply text-kh3-red; + } + + .nav-link-span { + @apply hidden md:inline; + } + + .project-overlay { + transform: translateY(100%); + opacity: 0; + transition: transform 0.4s ease-out, opacity 0.4s ease-out; + } + + + /* Menu Button Styles */ + #menuWrap { + position: relative; + overflow: visible; + } + + .menu-waves { + position: absolute; + inset: -20px; + z-index: 1; + pointer-events: none; + } + + #menuWrap.open #menuPetal { + opacity: 1; + } + + #menuWrap.open #menuGrid { + opacity: 0; + } + + .menu-outline { + position: absolute; + inset: 0; + z-index: 2; + pointer-events: none; + outline: 1px solid rgba(255, 255, 255, 0.6); + outline-offset: 6px; + } + + .menu-waves .wave { + position: absolute; + inset: 0; + border: 1px solid rgba(255, 255, 255, 0.28); + opacity: 0; + transform: scale(1); + animation: waveBurst 5.8s ease-in-out infinite; + will-change: transform, opacity; + } + + .menu-waves .wave:nth-child(2) { + animation-delay: 0.3s; + } + + .menu-waves .wave:nth-child(3) { + animation-delay: 0.6s; + } +} + +@layer base { + + /* General Animations */ + @keyframes spin { + from { + transform: scale(1.5) rotate(0deg); + } + + to { + transform: scale(1.5) rotate(360deg); + } + } + + @keyframes waveBurst { + + 0%, + 69% { + opacity: 0; + transform: scale(1); + } + + 77% { + opacity: 0.38; + transform: scale(1.18, 1.12); + } + + 92% { + opacity: 0.22; + transform: scale(1.55, 1.42); + } + + 100% { + opacity: 0; + transform: scale(1.95, 1.75); + } + } + + /* Page Transitions */ + @keyframes pageEnter { + 0% { + opacity: 0; + transform: scale(1.02); + } + + 100% { + opacity: 1; + transform: scale(1); + } + } + + @keyframes pageExit { + 0% { + opacity: 1; + transform: scale(1); + } + + 100% { + opacity: 0; + transform: scale(0.98); + } + } + + @keyframes staggerFadeOut { + 100% { + opacity: 0; + transform: translateY(-20px) scale(0.95); + } + } + + /* Image Slider Transitions */ + @keyframes slideOutLeft { + 100% { + transform: translateX(-100%) scale(0.8); + opacity: 0; + } + } + + @keyframes slideOutRight { + 100% { + transform: translateX(100%) scale(0.8); + opacity: 0; + } + } + + @keyframes zoomInFromLeft { + 0% { + transform: translateX(-100%) scale(1.3); + opacity: 0; + } + + 100% { + transform: translateX(0) scale(1); + opacity: 1; + } + } + + @keyframes zoomInFromRight { + 0% { + transform: translateX(100%) scale(1.3); + opacity: 0; + } + + 100% { + transform: translateX(0) scale(1); + opacity: 1; + } + } + + /* Specific Component Animations */ + @keyframes arrowPulse { + + 0%, + 100% { + transform: translateY(0); + opacity: 0.7; + } + + 50% { + transform: translateY(10px); + opacity: 1; + } + } + + .animate-arrowPulse { + animation: arrowPulse 2s ease-in-out infinite; + } + + @keyframes diagMaskReveal { + 0% { + opacity: 0; + clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%); + transform: scale(1.03); + } + + 55% { + opacity: 1; + clip-path: polygon(82% 0, 100% 0, 100% 100%, 64% 100%); + } + + 100% { + opacity: 1; + clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); + } + } + + /* NEW: Styles from about.html */ + @keyframes diamondPulse { + + 0%, + 100% { + transform: rotate(45deg) scale(1); + box-shadow: 0 0 0 rgba(220, 38, 38, 0); + } + + 50% { + transform: rotate(45deg) scale(0.8); + box-shadow: 0 0 0 rgba(220, 38, 38, 0); + } + + 75% { + transform: rotate(45deg) scale(1.1); + box-shadow: 0 0 15px rgba(220, 38, 38, 0.4), 0 0 25px rgba(220, 38, 38, 0.2); + } + } + + .diamond-pulse { + animation: diamondPulse 2s ease-in-out infinite; + } +} + +@layer components { + .value-item { + @apply cursor-pointer text-lg md:text-2xl font-semibold text-neutral-400 transition-all duration-300 md:pl-6 md:border-l-4 border-neutral-200; + } + + .value-item.active { + @apply text-kh3-red border-kh3-red; + transform: translateX(4px); + } + + .value-content-block { + @apply absolute opacity-0 transition-opacity duration-500 ease-in-out; + } + + .value-content-block.active { + @apply static opacity-100; + } + + /* Mobile (Card-based) Layout */ + @media (max-width: 767px) { + .value-content-block { + @apply static opacity-100 mb-8 p-6 border border-neutral-200 rounded-lg; + } + + .value-item { + @apply hidden; + /* Hide the list on mobile */ + } + } + + .form-input { + @apply w-full bg-neutral-900 border border-neutral-700 text-white px-4 py-3 rounded-md transition-colors duration-300; + @apply focus:outline-none focus:ring-2 focus:ring-kh3-red focus:border-transparent; + } + + .form-input::placeholder { + @apply text-neutral-500; + } + + .service-item { + @apply bg-neutral-900/50 border border-neutral-800 rounded-lg p-4 flex items-start gap-4 transition-all duration-300; + } + .service-item:hover { + @apply border-kh3-red/50 bg-neutral-900 scale-[1.02]; + } + .service-item-icon { + @apply w-5 h-5 text-kh3-red mt-1 flex-shrink-0; + } +} \ No newline at end of file diff --git a/styles/output.css b/styles/output.css new file mode 100644 index 0000000..1008191 --- /dev/null +++ b/styles/output.css @@ -0,0 +1,2890 @@ +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +/* +! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden]:where(:not([hidden="until-found"])) { + display: none; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.pointer-events-none { + pointer-events: none; +} + +.visible { + visibility: visible; +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.inset-0 { + inset: 0px; +} + +.inset-x-0 { + left: 0px; + right: 0px; +} + +.-bottom-4 { + bottom: -1rem; +} + +.-left-4 { + left: -1rem; +} + +.-right-4 { + right: -1rem; +} + +.-top-4 { + top: -1rem; +} + +.bottom-0 { + bottom: 0px; +} + +.bottom-10 { + bottom: 2.5rem; +} + +.bottom-12 { + bottom: 3rem; +} + +.bottom-16 { + bottom: 4rem; +} + +.bottom-4 { + bottom: 1rem; +} + +.bottom-6 { + bottom: 1.5rem; +} + +.bottom-8 { + bottom: 2rem; +} + +.left-0 { + left: 0px; +} + +.left-1\/2 { + left: 50%; +} + +.left-12 { + left: 3rem; +} + +.left-4 { + left: 1rem; +} + +.left-6 { + left: 1.5rem; +} + +.left-8 { + left: 2rem; +} + +.right-0 { + right: 0px; +} + +.right-4 { + right: 1rem; +} + +.right-6 { + right: 1.5rem; +} + +.right-8 { + right: 2rem; +} + +.top-0 { + top: 0px; +} + +.top-1\/2 { + top: 50%; +} + +.top-20 { + top: 5rem; +} + +.top-4 { + top: 1rem; +} + +.top-6 { + top: 1.5rem; +} + +.top-8 { + top: 2rem; +} + +.top-28 { + top: 7rem; +} + +.-bottom-2 { + bottom: -0.5rem; +} + +.-left-2 { + left: -0.5rem; +} + +.-right-2 { + right: -0.5rem; +} + +.-top-2 { + top: -0.5rem; +} + +.-z-10 { + z-index: -10; +} + +.z-10 { + z-index: 10; +} + +.z-20 { + z-index: 20; +} + +.z-40 { + z-index: 40; +} + +.z-50 { + z-index: 50; +} + +.z-30 { + z-index: 30; +} + +.z-\[60\] { + z-index: 60; +} + +.z-0 { + z-index: 0; +} + +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.-mt-1\.5 { + margin-top: -0.375rem; +} + +.mb-12 { + margin-bottom: 3rem; +} + +.mb-16 { + margin-bottom: 4rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-20 { + margin-bottom: 5rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.mb-8 { + margin-bottom: 2rem; +} + +.ml-0 { + margin-left: 0px; +} + +.ml-8 { + margin-left: 2rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-10 { + margin-top: 2.5rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mt-20 { + margin-top: 5rem; +} + +.mt-3 { + margin-top: 0.75rem; +} + +.mt-6 { + margin-top: 1.5rem; +} + +.mt-8 { + margin-top: 2rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.ml-3 { + margin-left: 0.75rem; +} + +.line-clamp-2 { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.grid { + display: grid; +} + +.hidden { + display: none; +} + +.h-1 { + height: 0.25rem; +} + +.h-1\.5 { + height: 0.375rem; +} + +.h-1\/2 { + height: 50%; +} + +.h-12 { + height: 3rem; +} + +.h-16 { + height: 4rem; +} + +.h-2 { + height: 0.5rem; +} + +.h-2\.5 { + height: 0.625rem; +} + +.h-20 { + height: 5rem; +} + +.h-3 { + height: 0.75rem; +} + +.h-32 { + height: 8rem; +} + +.h-5 { + height: 1.25rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-64 { + height: 16rem; +} + +.h-8 { + height: 2rem; +} + +.h-\[2px\] { + height: 2px; +} + +.h-\[60vh\] { + height: 60vh; +} + +.h-full { + height: 100%; +} + +.h-px { + height: 1px; +} + +.h-screen { + height: 100vh; +} + +.h-80 { + height: 20rem; +} + +.h-0\.5 { + height: 0.125rem; +} + +.h-24 { + height: 6rem; +} + +.h-3\/4 { + height: 75%; +} + +.h-4 { + height: 1rem; +} + +.h-\[55vh\] { + height: 55vh; +} + +.h-\[25vh\] { + height: 25vh; +} + +.h-\[75vh\] { + height: 75vh; +} + +.h-\[100dvh\] { + height: 100dvh; +} + +.h-\[20vh\] { + height: 20vh; +} + +.h-\[100svh\] { + height: 100svh; +} + +.h-7 { + height: 1.75rem; +} + +.max-h-\[90vh\] { + max-height: 90vh; +} + +.max-h-full { + max-height: 100%; +} + +.max-h-\[95vh\] { + max-height: 95vh; +} + +.min-h-\[90vh\] { + min-height: 90vh; +} + +.min-h-screen { + min-height: 100vh; +} + +.min-h-0 { + min-height: 0px; +} + +.w-0 { + width: 0px; +} + +.w-1 { + width: 0.25rem; +} + +.w-1\.5 { + width: 0.375rem; +} + +.w-1\/3 { + width: 33.333333%; +} + +.w-12 { + width: 3rem; +} + +.w-16 { + width: 4rem; +} + +.w-2 { + width: 0.5rem; +} + +.w-2\.5 { + width: 0.625rem; +} + +.w-2\/3 { + width: 66.666667%; +} + +.w-20 { + width: 5rem; +} + +.w-24 { + width: 6rem; +} + +.w-3 { + width: 0.75rem; +} + +.w-32 { + width: 8rem; +} + +.w-48 { + width: 12rem; +} + +.w-5 { + width: 1.25rem; +} + +.w-5\/6 { + width: 83.333333%; +} + +.w-6 { + width: 1.5rem; +} + +.w-64 { + width: 16rem; +} + +.w-8 { + width: 2rem; +} + +.w-full { + width: 100%; +} + +.w-px { + width: 1px; +} + +.w-1\/2 { + width: 50%; +} + +.w-4 { + width: 1rem; +} + +.w-7 { + width: 1.75rem; +} + +.min-w-0 { + min-width: 0px; +} + +.min-w-\[60px\] { + min-width: 60px; +} + +.max-w-2xl { + max-width: 42rem; +} + +.max-w-4xl { + max-width: 56rem; +} + +.max-w-5xl { + max-width: 64rem; +} + +.max-w-6xl { + max-width: 72rem; +} + +.max-w-7xl { + max-width: 80rem; +} + +.max-w-xl { + max-width: 36rem; +} + +.max-w-3xl { + max-width: 48rem; +} + +.max-w-full { + max-width: 100%; +} + +.flex-1 { + flex: 1 1 0%; +} + +.flex-shrink-0 { + flex-shrink: 0; +} + +.shrink-0 { + flex-shrink: 0; +} + +.grow { + flex-grow: 1; +} + +.-translate-x-1\/2 { + --tw-translate-x: -50%; + 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)); +} + +.-translate-y-1\/2 { + --tw-translate-y: -50%; + 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)); +} + +.-translate-y-full { + --tw-translate-y: -100%; + 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)); +} + +.translate-x-full { + --tw-translate-x: 100%; + 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)); +} + +.translate-y-full { + --tw-translate-y: 100%; + 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)); +} + +.translate-y-12 { + --tw-translate-y: 3rem; + 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)); +} + +.translate-y-8 { + --tw-translate-y: 2rem; + 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)); +} + +.-translate-x-1 { + --tw-translate-x: -0.25rem; + 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)); +} + +.-translate-x-full { + --tw-translate-x: -100%; + 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)); +} + +.-translate-y-1 { + --tw-translate-y: -0.25rem; + 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)); +} + +.translate-x-1 { + --tw-translate-x: 0.25rem; + 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)); +} + +.translate-y-1 { + --tw-translate-y: 0.25rem; + 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)); +} + +.rotate-45 { + --tw-rotate: 45deg; + 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)); +} + +.-rotate-45 { + --tw-rotate: -45deg; + 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)); +} + +.scale-95 { + --tw-scale-x: .95; + --tw-scale-y: .95; + 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)); +} + +.scale-100 { + --tw-scale-x: 1; + --tw-scale-y: 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)); +} + +.scale-y-\[-1\] { + --tw-scale-y: -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)); +} + +.transform { + 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)); +} + +@keyframes borderGlow { + 0%, 100% { + border-color: #ffffff; + box-shadow: 0 0 5px rgba(255, 255, 255, 0.3); + } + + 50% { + border-color: #B03037; + box-shadow: 0 0 15px rgba(176, 48, 55, 0.6); + } +} + +.animate-border-glow { + animation: borderGlow 3s ease-in-out infinite; +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + transform: translateX(-30px); + } + + 100% { + opacity: 1; + transform: translateX(0); + } +} + +.animate-fade-in-left { + animation: fadeInLeft 1s ease-out forwards; +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + transform: translateX(30px); + } + + 100% { + opacity: 1; + transform: translateX(0); + } +} + +.animate-fade-in-right { + animation: fadeInRight 1s ease-out forwards; +} + +@keyframes logoFloat { + 0%, 100% { + transform: translateY(0px); + } + + 50% { + transform: translateY(-10px); + } +} + +.animate-logo-float { + animation: logoFloat 3s ease-in-out infinite; +} + +@keyframes logoGlow { + 0%, 100% { + text-shadow: 0 0 1px rgba(255, 255, 255, 0.1), 0 0 1px rgba(176, 48, 55, 0.05); + filter: brightness(1); + } + + 50% { + text-shadow: 0 0 2px rgba(255, 255, 255, 0.15), 0 0 3px rgba(176, 48, 55, 0.08); + filter: brightness(1.02); + } +} + +.animate-logo-glow { + animation: logoGlow 3s ease-in-out infinite; +} + +@keyframes ping { + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} + +.animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} + +@keyframes pulse { + 50% { + opacity: .5; + } +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + transform: translateY(30px); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in-up { + animation: fadeInUp 1s ease-out forwards; +} + +.cursor-pointer { + cursor: pointer; +} + +.resize-none { + resize: none; +} + +.resize { + resize: both; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + +.flex-col { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.items-start { + align-items: flex-start; +} + +.items-center { + align-items: center; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-1 { + gap: 0.25rem; +} + +.gap-12 { + gap: 3rem; +} + +.gap-16 { + gap: 4rem; +} + +.gap-3 { + gap: 0.75rem; +} + +.gap-4 { + gap: 1rem; +} + +.gap-6 { + gap: 1.5rem; +} + +.gap-8 { + gap: 2rem; +} + +.gap-2 { + gap: 0.5rem; +} + +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.75rem * var(--tw-space-x-reverse)); + margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(2rem * var(--tw-space-x-reverse)); + margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-y-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); +} + +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + +.space-y-6 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); +} + +.space-y-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2rem * var(--tw-space-y-reverse)); +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-visible { + overflow: visible; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.overflow-x-hidden { + overflow-x: hidden; +} + +.whitespace-normal { + white-space: normal; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.rounded-2xl { + border-radius: 1rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-none { + border-radius: 0px; +} + +.border { + border-width: 1px; +} + +.border-2 { + border-width: 2px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-t { + border-top-width: 1px; +} + +.border-b-2 { + border-bottom-width: 2px; +} + +.border-r-2 { + border-right-width: 2px; +} + +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); +} + +.border-kh3-red { + --tw-border-opacity: 1; + border-color: rgb(176 48 55 / var(--tw-border-opacity, 1)); +} + +.border-neutral-800 { + --tw-border-opacity: 1; + border-color: rgb(38 38 38 / var(--tw-border-opacity, 1)); +} + +.border-white { + --tw-border-opacity: 1; + border-color: rgb(255 255 255 / var(--tw-border-opacity, 1)); +} + +.border-white\/10 { + border-color: rgb(255 255 255 / 0.1); +} + +.border-white\/30 { + border-color: rgb(255 255 255 / 0.3); +} + +.border-white\/20 { + border-color: rgb(255 255 255 / 0.2); +} + +.bg-\[\#1b2021\] { + --tw-bg-opacity: 1; + background-color: rgb(27 32 33 / var(--tw-bg-opacity, 1)); +} + +.bg-black { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1)); +} + +.bg-black\/30 { + background-color: rgb(0 0 0 / 0.3); +} + +.bg-black\/40 { + background-color: rgb(0 0 0 / 0.4); +} + +.bg-black\/60 { + background-color: rgb(0 0 0 / 0.6); +} + +.bg-kh3-black { + --tw-bg-opacity: 1; + background-color: rgb(33 40 41 / var(--tw-bg-opacity, 1)); +} + +.bg-kh3-grey { + --tw-bg-opacity: 1; + background-color: rgb(142 144 137 / var(--tw-bg-opacity, 1)); +} + +.bg-kh3-grey\/20 { + background-color: rgb(142 144 137 / 0.2); +} + +.bg-kh3-red { + --tw-bg-opacity: 1; + background-color: rgb(176 48 55 / var(--tw-bg-opacity, 1)); +} + +.bg-kh3-red\/30 { + background-color: rgb(176 48 55 / 0.3); +} + +.bg-kh3-red\/40 { + background-color: rgb(176 48 55 / 0.4); +} + +.bg-kh3-red\/50 { + background-color: rgb(176 48 55 / 0.5); +} + +.bg-kh3-red\/60 { + background-color: rgb(176 48 55 / 0.6); +} + +.bg-kh3-red\/70 { + background-color: rgb(176 48 55 / 0.7); +} + +.bg-neutral-800 { + --tw-bg-opacity: 1; + background-color: rgb(38 38 38 / var(--tw-bg-opacity, 1)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); +} + +.bg-white\/70 { + background-color: rgb(255 255 255 / 0.7); +} + +.bg-black\/50 { + background-color: rgb(0 0 0 / 0.5); +} + +.bg-black\/80 { + background-color: rgb(0 0 0 / 0.8); +} + +.bg-kh3-grey\/10 { + background-color: rgb(142 144 137 / 0.1); +} + +.bg-black\/90 { + background-color: rgb(0 0 0 / 0.9); +} + +.bg-white\/30 { + background-color: rgb(255 255 255 / 0.3); +} + +.bg-black\/70 { + background-color: rgb(0 0 0 / 0.7); +} + +.bg-black\/95 { + background-color: rgb(0 0 0 / 0.95); +} + +.bg-transparent { + background-color: transparent; +} + +.bg-red-500 { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1)); +} + +.bg-opacity-20 { + --tw-bg-opacity: 0.2; +} + +.bg-gradient-to-b { + background-image: linear-gradient(to bottom, var(--tw-gradient-stops)); +} + +.bg-gradient-to-br { + background-image: linear-gradient(to bottom right, var(--tw-gradient-stops)); +} + +.bg-gradient-to-r { + background-image: linear-gradient(to right, var(--tw-gradient-stops)); +} + +.from-kh3-black { + --tw-gradient-from: #212829 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(33 40 41 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-kh3-red { + --tw-gradient-from: #B03037 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(176 48 55 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-kh3-red\/20 { + --tw-gradient-from: rgb(176 48 55 / 0.2) var(--tw-gradient-from-position); + --tw-gradient-to: rgb(176 48 55 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-transparent { + --tw-gradient-from: transparent var(--tw-gradient-from-position); + --tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-white\/5 { + --tw-gradient-from: rgb(255 255 255 / 0.05) var(--tw-gradient-from-position); + --tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-gray-900 { + --tw-gradient-from: #111827 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.via-kh3-red { + --tw-gradient-to: rgb(176 48 55 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), #B03037 var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.via-transparent { + --tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), transparent var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.via-gray-800 { + --tw-gradient-to: rgb(31 41 55 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), #1f2937 var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.via-kh3-red\/40 { + --tw-gradient-to: rgb(176 48 55 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), rgb(176 48 55 / 0.4) var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.via-white\/10 { + --tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), rgb(255 255 255 / 0.1) var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.to-\[\#1b2021\] { + --tw-gradient-to: #1b2021 var(--tw-gradient-to-position); +} + +.to-black\/20 { + --tw-gradient-to: rgb(0 0 0 / 0.2) var(--tw-gradient-to-position); +} + +.to-kh3-grey\/40 { + --tw-gradient-to: rgb(142 144 137 / 0.4) var(--tw-gradient-to-position); +} + +.to-kh3-red\/20 { + --tw-gradient-to: rgb(176 48 55 / 0.2) var(--tw-gradient-to-position); +} + +.to-red-700 { + --tw-gradient-to: #b91c1c var(--tw-gradient-to-position); +} + +.to-transparent { + --tw-gradient-to: transparent var(--tw-gradient-to-position); +} + +.to-black { + --tw-gradient-to: #000000 var(--tw-gradient-to-position); +} + +.bg-cover { + background-size: cover; +} + +.bg-center { + background-position: center; +} + +.object-contain { + -o-object-fit: contain; + object-fit: contain; +} + +.object-cover { + -o-object-fit: cover; + object-fit: cover; +} + +.p-12 { + padding: 3rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-8 { + padding: 2rem; +} + +.p-6 { + padding: 1.5rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-4 { + padding: 1rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.px-8 { + padding-left: 2rem; + padding-right: 2rem; +} + +.py-16 { + padding-top: 4rem; + padding-bottom: 4rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-20 { + padding-top: 5rem; + padding-bottom: 5rem; +} + +.py-24 { + padding-top: 6rem; + padding-bottom: 6rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-32 { + padding-top: 8rem; + padding-bottom: 8rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.px-12 { + padding-left: 3rem; + padding-right: 3rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.px-16 { + padding-left: 4rem; + padding-right: 4rem; +} + +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.px-20 { + padding-left: 5rem; + padding-right: 5rem; +} + +.pb-1 { + padding-bottom: 0.25rem; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pl-16 { + padding-left: 4rem; +} + +.pl-28 { + padding-left: 7rem; +} + +.pr-6 { + padding-right: 1.5rem; +} + +.pt-20 { + padding-top: 5rem; +} + +.pt-24 { + padding-top: 6rem; +} + +.pt-4 { + padding-top: 1rem; +} + +.pt-8 { + padding-top: 2rem; +} + +.pt-32 { + padding-top: 8rem; +} + +.pb-2 { + padding-bottom: 0.5rem; +} + +.pl-20 { + padding-left: 5rem; +} + +.pr-8 { + padding-right: 2rem; +} + +.pl-8 { + padding-left: 2rem; +} + +.pt-16 { + padding-top: 4rem; +} + +.text-center { + text-align: center; +} + +.font-montserrat { + font-family: Montserrat, sans-serif; +} + +.font-calibri { + font-family: Calibri, sans-serif; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} + +.text-5xl { + font-size: 3rem; + line-height: 1; +} + +.text-6xl { + font-size: 3.75rem; + line-height: 1; +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-bold { + font-weight: 700; +} + +.font-extrabold { + font-weight: 800; +} + +.font-medium { + font-weight: 500; +} + +.font-semibold { + font-weight: 600; +} + +.uppercase { + text-transform: uppercase; +} + +.leading-relaxed { + line-height: 1.625; +} + +.tracking-\[0\.2em\] { + letter-spacing: 0.2em; +} + +.tracking-normal { + letter-spacing: 0em; +} + +.tracking-wide { + letter-spacing: 0.025em; +} + +.tracking-wider { + letter-spacing: 0.05em; +} + +.tracking-widest { + letter-spacing: 0.1em; +} + +.text-gray-800 { + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity, 1)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity, 1)); +} + +.text-kh3-black { + --tw-text-opacity: 1; + color: rgb(33 40 41 / var(--tw-text-opacity, 1)); +} + +.text-kh3-grey { + --tw-text-opacity: 1; + color: rgb(142 144 137 / var(--tw-text-opacity, 1)); +} + +.text-kh3-red { + --tw-text-opacity: 1; + color: rgb(176 48 55 / var(--tw-text-opacity, 1)); +} + +.text-neutral-300 { + --tw-text-opacity: 1; + color: rgb(212 212 212 / var(--tw-text-opacity, 1)); +} + +.text-neutral-400 { + --tw-text-opacity: 1; + color: rgb(163 163 163 / var(--tw-text-opacity, 1)); +} + +.text-neutral-600 { + --tw-text-opacity: 1; + color: rgb(82 82 82 / var(--tw-text-opacity, 1)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity, 1)); +} + +.text-white\/60 { + color: rgb(255 255 255 / 0.6); +} + +.text-white\/80 { + color: rgb(255 255 255 / 0.8); +} + +.text-white\/85 { + color: rgb(255 255 255 / 0.85); +} + +.text-white\/50 { + color: rgb(255 255 255 / 0.5); +} + +.text-white\/70 { + color: rgb(255 255 255 / 0.7); +} + +.underline { + text-decoration-line: underline; +} + +.opacity-0 { + opacity: 0; +} + +.opacity-100 { + opacity: 1; +} + +.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); +} + +.shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-xl { + --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); +} + +.outline { + outline-style: solid; +} + +.blur { + --tw-blur: blur(8px); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.blur-xl { + --tw-blur: blur(24px); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.drop-shadow-lg { + --tw-drop-shadow: drop-shadow(0 10px 8px rgb(0 0 0 / 0.04)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1)); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.drop-shadow { + --tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06)); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.grayscale { + --tw-grayscale: grayscale(100%); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.backdrop-blur-sm { + --tw-backdrop-blur: blur(4px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.backdrop-filter { + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.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; +} + +.transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-transform { + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.delay-300 { + transition-delay: 300ms; +} + +.delay-500 { + transition-delay: 500ms; +} + +.duration-300 { + transition-duration: 300ms; +} + +.duration-500 { + transition-duration: 500ms; +} + +.duration-1000 { + transition-duration: 1000ms; +} + +.ease-in-out { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} + +.ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +.hover\:-translate-y-2:hover { + --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)); +} + +.hover\:-translate-y-3:hover { + --tw-translate-y: -0.75rem; + 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\:scale-105:hover { + --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)); +} + +.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-kh3-red:hover { + --tw-border-opacity: 1; + border-color: rgb(176 48 55 / var(--tw-border-opacity, 1)); +} + +.hover\:border-red-700:hover { + --tw-border-opacity: 1; + border-color: rgb(185 28 28 / var(--tw-border-opacity, 1)); +} + +.hover\:border-white\/40:hover { + border-color: rgb(255 255 255 / 0.4); +} + +.hover\:bg-kh3-grey\/30:hover { + background-color: rgb(142 144 137 / 0.3); +} + +.hover\:bg-kh3-red:hover { + --tw-bg-opacity: 1; + background-color: rgb(176 48 55 / var(--tw-bg-opacity, 1)); +} + +.hover\:bg-kh3-red\/90:hover { + background-color: rgb(176 48 55 / 0.9); +} + +.hover\:bg-red-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(185 28 28 / var(--tw-bg-opacity, 1)); +} + +.hover\:bg-white:hover { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); +} + +.hover\:bg-black\/70:hover { + background-color: rgb(0 0 0 / 0.7); +} + +.hover\:tracking-\[0\.3em\]:hover { + letter-spacing: 0.3em; +} + +.hover\:text-kh3-red:hover { + --tw-text-opacity: 1; + color: rgb(176 48 55 / var(--tw-text-opacity, 1)); +} + +.hover\:text-white:hover { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity, 1)); +} + +.hover\:text-kh3-black:hover { + --tw-text-opacity: 1; + color: rgb(33 40 41 / var(--tw-text-opacity, 1)); +} + +.hover\:opacity-80:hover { + opacity: 0.8; +} + +.hover\:shadow-2xl:hover { + --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); +} + +.hover\:shadow-red-500\/25:hover { + --tw-shadow-color: rgb(239 68 68 / 0.25); + --tw-shadow: var(--tw-shadow-colored); +} + +.hover\:shadow-red-500\/50:hover { + --tw-shadow-color: rgb(239 68 68 / 0.5); + --tw-shadow: var(--tw-shadow-colored); +} + +.focus\:border-transparent:focus { + border-color: transparent; +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:ring-2:focus { + --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\:ring-kh3-red:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(176 48 55 / var(--tw-ring-opacity, 1)); +} + +.group:hover .group-hover\:w-32 { + width: 8rem; +} + +.group:hover .group-hover\:translate-x-2 { + --tw-translate-x: 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\:translate-x-full { + --tw-translate-x: 100%; + 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\:rotate-90 { + --tw-rotate: 90deg; + 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)); +} + +@keyframes ping { + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} + +.group:hover .group-hover\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} + +.group:hover .group-hover\:text-kh3-red { + --tw-text-opacity: 1; + color: rgb(176 48 55 / var(--tw-text-opacity, 1)); +} + +.group:hover .group-hover\:text-neutral-800 { + --tw-text-opacity: 1; + color: rgb(38 38 38 / var(--tw-text-opacity, 1)); +} + +.group:hover .group-hover\:text-red-400 { + --tw-text-opacity: 1; + color: rgb(248 113 113 / var(--tw-text-opacity, 1)); +} + +.group:hover .group-hover\:opacity-100 { + opacity: 1; +} + +.group:hover .group-hover\:shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.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); +} + +.group:hover .group-hover\:shadow-red-500\/20 { + --tw-shadow-color: rgb(239 68 68 / 0.2); + --tw-shadow: var(--tw-shadow-colored); +} + +.group:hover .group-hover\:shadow-red-500\/50 { + --tw-shadow-color: rgb(239 68 68 / 0.5); + --tw-shadow: var(--tw-shadow-colored); +} + +.group:hover .group-hover\:shadow-red-500\/30 { + --tw-shadow-color: rgb(239 68 68 / 0.3); + --tw-shadow: var(--tw-shadow-colored); +} + +.group:hover .group-hover\:blur-2xl { + --tw-blur: blur(40px); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +@media (min-width: 640px) { + .sm\:inline { + display: inline; + } + + .sm\:min-w-\[100px\] { + min-width: 100px; + } + + .sm\:gap-8 { + gap: 2rem; + } + + .sm\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + .sm\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } +} + +@media (min-width: 768px) { + .md\:fixed { + position: fixed; + } + + .md\:relative { + position: relative; + } + + .md\:top-28 { + top: 7rem; + } + + .md\:left-12 { + left: 3rem; + } + + .md\:bottom-12 { + bottom: 3rem; + } + + .md\:right-auto { + right: auto; + } + + .md\:top-auto { + top: auto; + } + + .md\:top-8 { + top: 2rem; + } + + .md\:ml-12 { + margin-left: 3rem; + } + + .md\:ml-20 { + margin-left: 5rem; + } + + .md\:ml-6 { + margin-left: 1.5rem; + } + + .md\:block { + display: block; + } + + .md\:inline { + display: inline; + } + + .md\:flex { + display: flex; + } + + .md\:hidden { + display: none; + } + + .md\:h-full { + height: 100%; + } + + .md\:h-0 { + height: 0px; + } + + .md\:h-auto { + height: auto; + } + + .md\:max-h-\[90vh\] { + max-height: 90vh; + } + + .md\:min-h-screen { + min-height: 100vh; + } + + .md\:w-1\/3 { + width: 33.333333%; + } + + .md\:w-2\/3 { + width: 66.666667%; + } + + .md\:w-8 { + width: 2rem; + } + + .md\:w-16 { + width: 4rem; + } + + .md\:flex-1 { + flex: 1 1 0%; + } + + .md\:flex-none { + flex: none; + } + + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .md\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .md\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .md\:flex-row { + flex-direction: row; + } + + .md\:items-center { + align-items: center; + } + + .md\:justify-center { + justify-content: center; + } + + .md\:gap-6 { + gap: 1.5rem; + } + + .md\:space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); + } + + .md\:space-x-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(2rem * var(--tw-space-x-reverse)); + margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); + } + + .md\: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)); + } + + .md\:whitespace-nowrap { + white-space: nowrap; + } + + .md\:p-8 { + padding: 2rem; + } + + .md\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + .md\:py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + } + + .md\:pt-12 { + padding-top: 3rem; + } + + .md\:pt-8 { + padding-top: 2rem; + } + + .md\:pl-28 { + padding-left: 7rem; + } + + .md\:text-2xl { + font-size: 1.5rem; + line-height: 2rem; + } + + .md\:text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; + } + + .md\:text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; + } + + .md\:text-5xl { + font-size: 3rem; + line-height: 1; + } + + .md\:text-6xl { + font-size: 3.75rem; + line-height: 1; + } + + .md\:text-7xl { + font-size: 4.5rem; + line-height: 1; + } + + .md\:text-8xl { + font-size: 6rem; + line-height: 1; + } + + .md\:text-base { + font-size: 1rem; + line-height: 1.5rem; + } + + .md\:text-lg { + font-size: 1.125rem; + line-height: 1.75rem; + } + + .md\:text-sm { + font-size: 0.875rem; + line-height: 1.25rem; + } + + .md\:tracking-\[0\.2em\] { + letter-spacing: 0.2em; + } +} + +@media (min-width: 1024px) { + .lg\:h-full { + height: 100%; + } + + .lg\:w-1\/3 { + width: 33.333333%; + } + + .lg\:w-2\/3 { + width: 66.666667%; + } + + .lg\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .lg\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .lg\:flex-row { + flex-direction: row; + } + + .lg\:gap-12 { + gap: 3rem; + } + + .lg\:gap-24 { + gap: 6rem; + } + + .lg\:text-6xl { + font-size: 3.75rem; + line-height: 1; + } +} + +@media (min-width: 1280px) { + .xl\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..afddbb8 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,95 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./*.html", "./js/*.js"], + safelist: [ + 'animate-fade-in-right', + 'animate-fade-in-up', + 'animate-fade-in-left', + // Add any other dynamically generated animation classes here + ], + darkMode: "class", + theme: { + extend: { + colors: { + kh3: { + black: "#212829", + red: "#B03037", + grey: "#8E9089", + white: "#FFFFFF", + gold: "#b8860b", + darkGold: "#8b6914", + lightGold: "#daa520", + }, + black: "#000000", + white: "#ffffff", + }, + fontFamily: { + montserrat: ["Montserrat", "sans-serif"], + calibri: ["Calibri", "sans-serif"], + }, + animation: { + "logo-float": "logoFloat 3s ease-in-out infinite", + "text-float": "textFloat 4s ease-in-out infinite", + "border-glow": "borderGlow 3s ease-in-out infinite", + "menu-grid-cycle": "menuGridCycle 15s ease-in-out infinite", + "fade-in-up": "fadeInUp 1s ease-out forwards", + "fade-in-left": "fadeInLeft 1s ease-out forwards", + "fade-in-right": "fadeInRight 1s ease-out forwards", // Corrected and verified + "fade-in-center": "fadeInCenter 1s ease-out forwards", + "logo-glow": "logoGlow 3s ease-in-out infinite", + }, + keyframes: { + logoFloat: { + "0%, 100%": { transform: "translateY(0px)" }, + "50%": { transform: "translateY(-10px)" }, + }, + textFloat: { + "0%, 100%": { transform: "translateY(0px)" }, + "50%": { transform: "translateY(-5px)" }, + }, + borderGlow: { + "0%, 100%": { + borderColor: "#ffffff", + boxShadow: "0 0 5px rgba(255, 255, 255, 0.3)", + }, + "50%": { + borderColor: "#B03037", + boxShadow: "0 0 15px rgba(176, 48, 55, 0.6)", + }, + }, + menuGridCycle: { + // ... content ... + }, + fadeInUp: { + "0%": { opacity: "0", transform: "translateY(30px)" }, + "100%": { opacity: "1", transform: "translateY(0)" }, + }, + fadeInLeft: { + "0%": { opacity: "0", transform: "translateX(-30px)" }, + "100%": { opacity: "1", transform: "translateX(0)" }, + }, + fadeInRight: { // Corrected and verified + "0%": { opacity: "0", transform: "translateX(30px)" }, + "100%": { opacity: "1", transform: "translateX(0)" }, + }, + fadeInCenter: { + "0%": { opacity: "0", transform: "scale(0.9)" }, + "100%": { opacity: "1", transform: "scale(1)" }, + }, + logoGlow: { + "0%, 100%": { + textShadow: + "0 0 1px rgba(255, 255, 255, 0.1), 0 0 1px rgba(176, 48, 55, 0.05)", + filter: "brightness(1)", + }, + "50%": { + textShadow: + "0 0 2px rgba(255, 255, 255, 0.15), 0 0 3px rgba(176, 48, 55, 0.08)", + filter: "brightness(1.02)", + }, + }, + }, + }, + }, + plugins: [], +}; diff --git a/who.html b/who.html new file mode 100644 index 0000000..b180dab --- /dev/null +++ b/who.html @@ -0,0 +1,195 @@ + + + + + + + Who - KH3 + + + + + + + + + + + + + + + + +
    + + KH3 + +
    + + +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    WHO

    +
    +
    +
    +
    +
    + KH3 Team + +
    +
    +
    + +
    +
    +
    +

    TEAM

    +
    +
    + MEET THE KH3 TEAM +
    +
    +

    WE'RE AN + EVER-EXPANDING FAMILY OF DESIGN AND CONSTRUCTION CRAFTSMEN AND PROJECT MANAGEMENT EXPERTS WHO BELIEVE IN + DELIVERING HIGH QUALITY SOLUTIONS.

    +
    + + +
    + +
    +
    +
    +
    + +
    + +
    + + + +
    +
    + + KH3 + +
    +
    +
    +
    +
    + + + + + \ No newline at end of file