Initial commit: add FothiFihaara landingpage
This commit is contained in:
commit
d2a5fe5afd
7 changed files with 593 additions and 0 deletions
18
README.md
Normal file
18
README.md
Normal 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
BIN
images/materials.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
BIN
images/services.webp
Normal file
BIN
images/services.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
BIN
images/tools.webp
Normal file
BIN
images/tools.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
123
index.html
Normal file
123
index.html
Normal 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
75
script.js
Normal 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
377
styles.css
Normal 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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue