Initial commit: add FothiFihaara landingpage

This commit is contained in:
invosset 2026-06-21 11:43:36 +08:00
commit d2a5fe5afd
7 changed files with 593 additions and 0 deletions

18
README.md Normal file
View file

@ -0,0 +1,18 @@
# FothiFihaara.com Landing Page
A premium black/white landing page for FothiFihaara.com, a directory of textile materials, tools, and services.
## Preview locally
Open `index.html` in any web browser.
## Features
- Dark and light mode toggle
- Scroll reveal animations
- Responsive layout
- Placeholder directory cards
## Deployment
This site is deployed via Coolify from the `master` branch on Forgejo.

BIN
images/materials.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
images/services.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
images/tools.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

123
index.html Normal file
View file

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FothiFihaara.com — Textile Materials, Tools & Services</title>
<meta name="description" content="A directory of textile materials, tools, and services. Connecting suppliers and makers.">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<div class="container header-inner">
<a href="#" class="brand">FothiFihaara.com</a>
<nav class="main-nav">
<a href="#about">About</a>
<a href="#directory">Directory</a>
<a href="#join">Join</a>
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle dark mode"></button>
</nav>
</div>
</header>
<main>
<section class="hero">
<div class="container">
<p class="label">The textile network</p>
<h1>A directory of textile<br>materials, tools, and services</h1>
<p class="subtitle">Connecting suppliers and makers in one curated place.</p>
<div class="hero-actions">
<a href="#join" class="btn btn-primary">Join as a Supplier</a>
<a href="#directory" class="btn btn-secondary">Explore the Directory</a>
</div>
</div>
</section>
<section id="directory" class="directory-preview">
<div class="container">
<h2>Directory Preview</h2>
<div class="cards">
<article class="card">
<img src="images/materials.webp" alt="Textile materials preview">
<div class="card-body">
<span class="category">Materials</span>
<h3>Premium Cotton Blends</h3>
<p>Supplier: Nordic Textiles</p>
</div>
</article>
<article class="card">
<img src="images/tools.webp" alt="Textile tools preview">
<div class="card-body">
<span class="category">Tools</span>
<h3>Industrial Looms</h3>
<p>Service: WeaveTech</p>
</div>
</article>
<article class="card">
<img src="images/services.webp" alt="Textile services preview">
<div class="card-body">
<span class="category">Services</span>
<h3>Dyeing & Finishing</h3>
<p>Supplier: ColorWorks</p>
</div>
</article>
</div>
</div>
</section>
<section id="about" class="benefits">
<div class="container">
<h2>Why Join?</h2>
<div class="benefit-grid">
<div class="benefit">
<div class="benefit-icon"></div>
<h3>Reach buyers</h3>
<p>Get discovered by makers actively looking for suppliers.</p>
</div>
<div class="benefit">
<div class="benefit-icon"></div>
<h3>Premium placement</h3>
<p>Curated listings, not a crowded marketplace.</p>
</div>
<div class="benefit">
<div class="benefit-icon"></div>
<h3>Direct contact</h3>
<p>Visitors reach you via your preferred messaging app.</p>
</div>
</div>
</div>
</section>
<section id="join" class="join-cta">
<div class="container">
<h2>Ready to list your business?</h2>
<p>Send us a message and we will guide you through the process.</p>
<a href="#contact" class="btn btn-primary">Contact us</a>
<div class="social-links">
<a href="https://x.com/" target="_blank" rel="noopener noreferrer">X</a>
<a href="https://facebook.com/" target="_blank" rel="noopener noreferrer">Facebook</a>
<a href="https://vk.com/" target="_blank" rel="noopener noreferrer">VK</a>
</div>
</div>
</section>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<div class="footer-brand">FothiFihaara.com</div>
<p class="footer-tagline">A directory of textile materials, tools, and services</p>
<p class="copyright">
Copyright © 2023 - <span id="current-year">2026</span> FothiFihaara.com. All rights reserved. All trademarks and brands are the property of their respective owners.
</p>
<p class="credit">
<a href="https://invosset.com/" target="_blank" rel="noopener noreferrer">Online Promotion</a>
&
<a href="https://invosset.com/" target="_blank" rel="noopener noreferrer">Managed Advertising</a>
by Invosset
</p>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>

75
script.js Normal file
View file

@ -0,0 +1,75 @@
// Theme toggle with localStorage
const themeToggle = document.getElementById('theme-toggle');
const html = document.documentElement;
const savedTheme = localStorage.getItem('theme');
function applyTheme(theme) {
if (theme === 'light') {
html.setAttribute('data-theme', 'light');
themeToggle.textContent = '☀';
themeToggle.setAttribute('aria-label', 'Switch to dark mode');
} else {
html.removeAttribute('data-theme');
themeToggle.textContent = '☾';
themeToggle.setAttribute('aria-label', 'Switch to light mode');
}
}
if (savedTheme) {
applyTheme(savedTheme);
}
themeToggle.addEventListener('click', () => {
const current = html.getAttribute('data-theme');
const next = current === 'light' ? 'dark' : 'light';
applyTheme(next);
localStorage.setItem('theme', next);
});
// Dynamic current year in footer
const yearSpan = document.getElementById('current-year');
if (yearSpan) {
yearSpan.textContent = new Date().getFullYear();
}
// Scroll reveal animation
const revealElements = document.querySelectorAll('section');
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.classList.add('visible');
}, index * 80);
revealObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.15,
rootMargin: '0px 0px -40px 0px'
});
revealElements.forEach((el) => {
el.classList.add('reveal');
revealObserver.observe(el);
});
// Stagger cards inside directory preview
const cards = document.querySelectorAll('.card');
const cardObserver = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.classList.add('visible');
}, index * 120);
cardObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.2
});
cards.forEach((card) => {
card.classList.add('reveal');
cardObserver.observe(card);
});

377
styles.css Normal file
View file

@ -0,0 +1,377 @@
:root {
--bg: #0a0a0a;
--surface: #111;
--surface-2: #1a1a1a;
--text: #f5f5f5;
--text-muted: #888;
--border: #222;
--accent: #fff;
}
[data-theme="light"] {
--bg: #fafafa;
--surface: #fff;
--surface-2: #f2f2f2;
--text: #111;
--text-muted: #666;
--border: #e5e5e5;
--accent: #000;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background-color: var(--bg);
color: var(--text);
line-height: 1.6;
transition: background-color 0.3s ease, color 0.3s ease;
}
.container {
width: 90%;
max-width: 1100px;
margin: 0 auto;
padding: 0 1rem;
}
.site-header {
padding: 1.25rem 0;
border-bottom: 1px solid var(--border);
background-color: var(--bg);
position: sticky;
top: 0;
z-index: 100;
}
.header-inner {
display: flex;
justify-content: space-between;
align-items: center;
}
.brand {
font-size: 1.125rem;
font-weight: 500;
color: var(--text);
text-decoration: none;
letter-spacing: 0.01em;
}
.main-nav {
display: flex;
align-items: center;
gap: 1.5rem;
}
.main-nav a {
color: var(--text-muted);
text-decoration: none;
font-size: 0.9rem;
transition: color 0.2s ease;
}
.main-nav a:hover {
color: var(--text);
}
.theme-toggle {
background: transparent;
border: 1px solid var(--border);
color: var(--text);
width: 2rem;
height: 2rem;
border-radius: 50%;
cursor: pointer;
font-size: 1rem;
line-height: 1;
transition: transform 0.2s ease, border-color 0.2s ease;
}
.theme-toggle:hover {
transform: scale(1.05);
border-color: var(--text-muted);
}
.hero {
text-align: center;
padding: 6rem 0 5rem;
}
.hero .label {
text-transform: uppercase;
letter-spacing: 0.15em;
font-size: 0.8rem;
color: var(--text-muted);
margin-bottom: 1rem;
}
.hero h1 {
font-size: clamp(2rem, 5vw, 3.25rem);
font-weight: 300;
line-height: 1.15;
margin-bottom: 1rem;
}
.hero .subtitle {
font-size: 1.125rem;
color: var(--text-muted);
max-width: 32rem;
margin: 0 auto 2rem;
}
.hero-actions {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.btn {
display: inline-block;
padding: 0.85rem 1.75rem;
border-radius: 999px;
text-decoration: none;
font-weight: 600;
font-size: 0.95rem;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.btn:hover {
transform: translateY(-2px);
}
.btn-primary {
background-color: var(--accent);
color: var(--bg);
}
.btn-secondary {
background-color: transparent;
color: var(--text);
border: 1px solid var(--border);
}
.directory-preview,
.benefits,
.join-cta {
padding: 4rem 0;
}
.directory-preview h2,
.benefits h2,
.join-cta h2 {
text-align: center;
font-weight: 400;
font-size: 1.75rem;
margin-bottom: 2.5rem;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
.card {
background-color: var(--surface);
border: 1px solid var(--border);
border-radius: 1rem;
overflow: hidden;
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.card:hover {
transform: translateY(-6px);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}
.card img {
width: 100%;
height: 180px;
object-fit: cover;
display: block;
}
.card-body {
padding: 1.25rem;
}
.card .category {
text-transform: uppercase;
font-size: 0.7rem;
letter-spacing: 0.1em;
color: var(--text-muted);
}
.card h3 {
font-size: 1.15rem;
font-weight: 600;
margin: 0.5rem 0 0.25rem;
}
.card p {
font-size: 0.9rem;
color: var(--text-muted);
}
.benefit-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 2rem;
max-width: 800px;
margin: 0 auto;
text-align: center;
}
.benefit-icon {
font-size: 1.5rem;
margin-bottom: 0.5rem;
color: var(--text-muted);
}
.benefit h3 {
font-size: 1.1rem;
margin-bottom: 0.5rem;
}
.benefit p {
font-size: 0.9rem;
color: var(--text-muted);
}
.join-cta {
background-color: var(--surface);
text-align: center;
}
.join-cta p {
color: var(--text-muted);
margin-bottom: 1.5rem;
}
.social-links {
display: flex;
justify-content: center;
gap: 1.5rem;
margin-top: 2rem;
}
.social-links a {
color: var(--text-muted);
text-decoration: none;
font-size: 0.9rem;
transition: color 0.2s ease;
}
.social-links a:hover {
color: var(--text);
}
.site-footer {
background-color: var(--surface-2);
padding: 4rem 0 3rem;
text-align: center;
border-top: 1px solid var(--border);
}
.footer-brand {
font-size: 1.75rem;
font-weight: 500;
margin-bottom: 0.25rem;
}
.footer-tagline {
color: var(--text-muted);
margin-bottom: 2rem;
}
.copyright,
.credit {
font-size: 0.8rem;
color: var(--text-muted);
max-width: 700px;
margin: 0 auto 1rem;
}
.credit a {
color: var(--text);
text-decoration: none;
}
.reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
@media (max-width: 600px) {
.header-inner {
flex-wrap: wrap;
gap: 0.75rem;
}
.main-nav {
gap: 1rem;
}
.hero {
padding: 4rem 0 3rem;
}
.hero-actions {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 280px;
text-align: center;
}
.directory-preview,
.benefits,
.join-cta {
padding: 3rem 0;
}
.directory-preview h2,
.benefits h2,
.join-cta h2 {
font-size: 1.5rem;
}
.footer-brand {
font-size: 1.5rem;
}
.copyright,
.credit {
font-size: 0.75rem;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}