chore: modularize ui components
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
export default function Footer() {
|
||||||
|
return (
|
||||||
|
<footer className="footer">
|
||||||
|
<div className="footer-content">
|
||||||
|
<p>
|
||||||
|
Built with <span className="heart">❤️</span> and Amara Chukwu
|
||||||
|
</p>
|
||||||
|
<p className="footer-year">© {new Date().getFullYear()}</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
export default function Header({ showNavLinks = true }) {
|
||||||
|
return (
|
||||||
|
<header className="header">
|
||||||
|
<nav className="navbar">
|
||||||
|
<div className="logo">
|
||||||
|
<Link href="/">
|
||||||
|
<span className="logo-text">JE</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
{showNavLinks && (
|
||||||
|
<div className="nav-links">
|
||||||
|
<Link href="/" className="nav-link">
|
||||||
|
Home
|
||||||
|
</Link>
|
||||||
|
<Link href="/rates" className="nav-link cta">
|
||||||
|
Rates
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!showNavLinks && (
|
||||||
|
<div className="nav-links">
|
||||||
|
<a href="mailto:me@jesseinit.dev" className="nav-link cta">
|
||||||
|
Get in touch
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import Head from 'next/head';
|
||||||
|
import Header from './Header';
|
||||||
|
import Footer from './Footer';
|
||||||
|
|
||||||
|
export default function Layout({ children, title, description, showNavLinks = true }) {
|
||||||
|
return (
|
||||||
|
<div className="container">
|
||||||
|
<Head>
|
||||||
|
<title>{title || 'Jesse Egbosionu - Software Engineer'}</title>
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content={description || 'Software engineer based in Amsterdam, focused on building scalable backend systems.'}
|
||||||
|
/>
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<Header showNavLinks={showNavLinks} />
|
||||||
|
|
||||||
|
<main className="main-content">{children}</main>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export default function RateCard({ provider, rate, href, isBest, index, formatCurrency }) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className={`rate-card ${isBest ? 'best' : ''}`}
|
||||||
|
style={{ animationDelay: `${index * 0.1}s` }}
|
||||||
|
>
|
||||||
|
<div className="rate-card-header">
|
||||||
|
<h3 className="provider-name">{provider}</h3>
|
||||||
|
{isBest && <span className="best-badge">Best Rate</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="rate-value">{formatCurrency(rate)}</div>
|
||||||
|
|
||||||
|
<div className="rate-card-footer">
|
||||||
|
<span className="visit-link">Visit provider →</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
const socialData = [
|
||||||
|
{
|
||||||
|
name: 'GitHub',
|
||||||
|
url: 'https://github.com/jesseinit',
|
||||||
|
icon: (
|
||||||
|
<svg className="social-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'LinkedIn',
|
||||||
|
url: 'https://linkedin.com/in/jesse-egbosionu/',
|
||||||
|
icon: (
|
||||||
|
<svg className="social-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Twitter',
|
||||||
|
url: 'https://twitter.com/jesseinit/',
|
||||||
|
icon: (
|
||||||
|
<svg className="social-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function SocialLinks() {
|
||||||
|
return (
|
||||||
|
<div className="social-links">
|
||||||
|
{socialData.map((social) => (
|
||||||
|
<a
|
||||||
|
key={social.name}
|
||||||
|
href={social.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="social-link"
|
||||||
|
>
|
||||||
|
{social.icon}
|
||||||
|
{social.name}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
+37
-81
@@ -1,94 +1,50 @@
|
|||||||
import Head from 'next/head';
|
import Layout from '../components/Layout';
|
||||||
|
import SocialLinks from '../components/SocialLinks';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<Layout showNavLinks={false}>
|
||||||
<Head>
|
<section className="hero">
|
||||||
<title>Jesse Egbosionu - Software Engineer</title>
|
<div className="hero-content">
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<h1 className="hero-title">
|
||||||
<meta name="description" content="Software engineer based in Amsterdam, focused on building scalable backend systems." />
|
Hey, I'm <span className="highlight">Jesse Egbosionu</span>
|
||||||
</Head>
|
</h1>
|
||||||
|
|
||||||
<header className="header">
|
<p className="hero-subtitle">
|
||||||
<nav className="navbar">
|
Software Engineer crafting scalable backend systems in Amsterdam
|
||||||
<div className="logo">
|
</p>
|
||||||
<span className="logo-text">JE</span>
|
|
||||||
</div>
|
|
||||||
<div className="nav-links">
|
|
||||||
<a href="mailto:me@jesseinit.dev" className="nav-link cta">Get in touch</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main className="main-content">
|
<div className="hero-description">
|
||||||
<section className="hero">
|
<p>
|
||||||
<div className="hero-content">
|
I build and scale software backends with a focus on creating impact through
|
||||||
<h1 className="hero-title">
|
teamwork and continuous learning. My passion lies in solving complex problems
|
||||||
Hey, I'm <span className="highlight">Jesse Egbosionu</span>
|
and delivering solutions that enrich people's lives.
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p className="hero-subtitle">
|
|
||||||
Software Engineer crafting scalable backend systems in Amsterdam
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="hero-description">
|
<p>
|
||||||
<p>
|
Over the past 6 years, I've shipped products across <strong>finance</strong>, <strong>ecommerce</strong>,
|
||||||
I build and scale software backends with a focus on creating impact through
|
and <strong>logistics</strong>, working with technologies like Python (Django, FastAPI),
|
||||||
teamwork and continuous learning. My passion lies in solving complex problems
|
JavaScript (React, Node.js), PostgreSQL, Docker, Redis, and Kubernetes.
|
||||||
and delivering solutions that enrich people's lives.
|
</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Over the past 6 years, I've shipped products across <strong>finance</strong>, <strong>ecommerce</strong>,
|
|
||||||
and <strong>logistics</strong>, working with technologies like Python (Django, FastAPI),
|
|
||||||
JavaScript (React, Node.js), PostgreSQL, Docker, Redis, and Kubernetes.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="social-links">
|
|
||||||
<a href="https://github.com/jesseinit" target="_blank" rel="noopener noreferrer" className="social-link">
|
|
||||||
<svg className="social-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
|
||||||
</svg>
|
|
||||||
GitHub
|
|
||||||
</a>
|
|
||||||
<a href="https://linkedin.com/in/jesse-egbosionu/" target="_blank" rel="noopener noreferrer" className="social-link">
|
|
||||||
<svg className="social-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
|
|
||||||
</svg>
|
|
||||||
LinkedIn
|
|
||||||
</a>
|
|
||||||
<a href="https://twitter.com/jesseinit/" target="_blank" rel="noopener noreferrer" className="social-link">
|
|
||||||
<svg className="social-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
|
||||||
</svg>
|
|
||||||
Twitter
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a href="mailto:me@jesseinit.dev" className="primary-cta">
|
|
||||||
<span>Let's work together</span>
|
|
||||||
<span className="arrow">→</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="hero-image-wrapper">
|
<SocialLinks />
|
||||||
<div className="image-backdrop"></div>
|
|
||||||
<img
|
|
||||||
src="hero.jpg"
|
|
||||||
alt="Jesse Egbosionu"
|
|
||||||
className="hero-image"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer className="footer">
|
<a href="mailto:me@jesseinit.dev" className="primary-cta">
|
||||||
<div className="footer-content">
|
<span>Let's work together</span>
|
||||||
<p>Built with <span className="heart">❤️</span> and Amara Chukwu</p>
|
<span className="arrow">→</span>
|
||||||
<p className="footer-year">© {new Date().getFullYear()}</p>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
|
||||||
</div>
|
<div className="hero-image-wrapper">
|
||||||
|
<div className="image-backdrop"></div>
|
||||||
|
<img
|
||||||
|
src="hero.jpg"
|
||||||
|
alt="Jesse Egbosionu"
|
||||||
|
className="hero-image"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-118
@@ -1,5 +1,6 @@
|
|||||||
import Head from "next/head";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import Layout from "../components/Layout";
|
||||||
|
import RateCard from "../components/RateCard";
|
||||||
import { fetchData } from "../utils/api";
|
import { fetchData } from "../utils/api";
|
||||||
|
|
||||||
export default function Rates() {
|
export default function Rates() {
|
||||||
@@ -47,136 +48,95 @@ export default function Rates() {
|
|||||||
}) : null;
|
}) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<Layout
|
||||||
<Head>
|
title="EUR to NGN Exchange Rates - Jesse Egbosionu"
|
||||||
<title>EUR to NGN Exchange Rates - Jesse Egbosionu</title>
|
description="Compare live EUR to NGN exchange rates across multiple providers."
|
||||||
<link rel="icon" href="/favicon.ico" />
|
showNavLinks={true}
|
||||||
<meta name="description" content="Compare live EUR to NGN exchange rates across multiple providers." />
|
>
|
||||||
</Head>
|
<section className="rates-section">
|
||||||
|
<div className="rates-header">
|
||||||
<header className="header">
|
<div className="rates-title-group">
|
||||||
<nav className="navbar">
|
<h1 className="rates-title">Exchange Rates</h1>
|
||||||
<div className="logo">
|
<p className="rates-subtitle">
|
||||||
<a href="/">
|
Compare live EUR to NGN rates across providers
|
||||||
<span className="logo-text">JE</span>
|
</p>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="nav-links">
|
|
||||||
<a href="/" className="nav-link">Home</a>
|
|
||||||
<a href="/rates" className="nav-link cta">Rates</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main className="main-content">
|
<div className="currency-display">
|
||||||
<section className="rates-section">
|
<div className="currency-badge">
|
||||||
<div className="rates-header">
|
<span className="currency-from">€1 EUR</span>
|
||||||
<div className="rates-title-group">
|
<span className="currency-arrow">→</span>
|
||||||
<h1 className="rates-title">Exchange Rates</h1>
|
<span className="currency-to">NGN</span>
|
||||||
<p className="rates-subtitle">
|
|
||||||
Compare live EUR to NGN rates across providers
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="currency-display">
|
{loading && (
|
||||||
<div className="currency-badge">
|
<div className="rates-grid">
|
||||||
<span className="currency-from">€1 EUR</span>
|
{[...Array(6)].map((_, index) => (
|
||||||
<span className="currency-arrow">→</span>
|
<div key={index} className="rate-card skeleton">
|
||||||
<span className="currency-to">NGN</span>
|
<div className="skeleton-header"></div>
|
||||||
|
<div className="skeleton-rate"></div>
|
||||||
|
<div className="skeleton-badge"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{loading && (
|
{error && (
|
||||||
|
<div className="error-state">
|
||||||
|
<div className="error-icon">⚠️</div>
|
||||||
|
<h3 className="error-title">Unable to load rates</h3>
|
||||||
|
<p className="error-message">{error}</p>
|
||||||
|
<button
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
className="retry-button"
|
||||||
|
>
|
||||||
|
Try again
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && !error && sortedData && sortedData.length > 0 && (
|
||||||
|
<>
|
||||||
<div className="rates-grid">
|
<div className="rates-grid">
|
||||||
{[...Array(6)].map((_, index) => (
|
{sortedData.map((item, index) => (
|
||||||
<div key={index} className="rate-card skeleton">
|
<RateCard
|
||||||
<div className="skeleton-header"></div>
|
key={item.provider}
|
||||||
<div className="skeleton-rate"></div>
|
provider={item.provider}
|
||||||
<div className="skeleton-badge"></div>
|
rate={item.rate}
|
||||||
</div>
|
href={item.href}
|
||||||
|
isBest={item.bestRate || item.rate === bestRate}
|
||||||
|
index={index}
|
||||||
|
formatCurrency={formatCurrency}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{error && (
|
<div className="rates-info">
|
||||||
<div className="error-state">
|
<p className="info-text">
|
||||||
<div className="error-icon">⚠️</div>
|
Rates are updated regularly. Click on a provider to visit their website.
|
||||||
<h3 className="error-title">Unable to load rates</h3>
|
</p>
|
||||||
<p className="error-message">{error}</p>
|
<p className="info-timestamp">
|
||||||
<button
|
Last updated: {new Date().toLocaleString('en-GB', {
|
||||||
onClick={() => window.location.reload()}
|
dateStyle: 'medium',
|
||||||
className="retry-button"
|
timeStyle: 'short'
|
||||||
>
|
})}
|
||||||
Try again
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!loading && !error && sortedData && sortedData.length > 0 && (
|
|
||||||
<>
|
|
||||||
<div className="rates-grid">
|
|
||||||
{sortedData.map((item, index) => (
|
|
||||||
<a
|
|
||||||
key={item.provider}
|
|
||||||
href={item.href}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={`rate-card ${item.bestRate || item.rate === bestRate ? 'best' : ''}`}
|
|
||||||
style={{ animationDelay: `${index * 0.1}s` }}
|
|
||||||
>
|
|
||||||
<div className="rate-card-header">
|
|
||||||
<h3 className="provider-name">{item.provider}</h3>
|
|
||||||
{(item.bestRate || item.rate === bestRate) && (
|
|
||||||
<span className="best-badge">Best Rate</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="rate-value">
|
|
||||||
{formatCurrency(item.rate)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="rate-card-footer">
|
|
||||||
<span className="visit-link">
|
|
||||||
Visit provider →
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="rates-info">
|
|
||||||
<p className="info-text">
|
|
||||||
Rates are updated regularly. Click on a provider to visit their website.
|
|
||||||
</p>
|
|
||||||
<p className="info-timestamp">
|
|
||||||
Last updated: {new Date().toLocaleString('en-GB', {
|
|
||||||
dateStyle: 'medium',
|
|
||||||
timeStyle: 'short'
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!loading && !error && (!data || data.length === 0) && (
|
|
||||||
<div className="empty-state">
|
|
||||||
<div className="empty-icon">📊</div>
|
|
||||||
<h3 className="empty-title">No rates available</h3>
|
|
||||||
<p className="empty-message">
|
|
||||||
We couldn't find any exchange rates at the moment.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</>
|
||||||
</section>
|
)}
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer className="footer">
|
{!loading && !error && (!data || data.length === 0) && (
|
||||||
<div className="footer-content">
|
<div className="empty-state">
|
||||||
<p>Built with <span className="heart">❤️</span> and Amara Chukwu</p>
|
<div className="empty-icon">📊</div>
|
||||||
<p className="footer-year">© {new Date().getFullYear()}</p>
|
<h3 className="empty-title">No rates available</h3>
|
||||||
</div>
|
<p className="empty-message">
|
||||||
</footer>
|
We couldn't find any exchange rates at the moment.
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -81,7 +81,7 @@ strong {
|
|||||||
// HEADER
|
// HEADER
|
||||||
.header {
|
.header {
|
||||||
padding: var(--spacing-lg) 0;
|
padding: var(--spacing-lg) 0;
|
||||||
border-bottom: 2px solid var(--color-primary);
|
border-bottom: 1px solid var(--color-primary);
|
||||||
background: rgba(255, 254, 240, 0.95);
|
background: rgba(255, 254, 240, 0.95);
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@@ -105,7 +105,7 @@ strong {
|
|||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
padding: 0.25rem 0.75rem;
|
padding: 0.25rem 0.75rem;
|
||||||
border: 2px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ strong {
|
|||||||
&.cta {
|
&.cta {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
border: 2px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--color-accent-hover);
|
background: var(--color-accent-hover);
|
||||||
@@ -175,7 +175,7 @@ strong {
|
|||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
border-bottom: 4px solid var(--color-primary);
|
border-bottom: 2px solid var(--color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ strong {
|
|||||||
gap: var(--spacing-xs);
|
gap: var(--spacing-xs);
|
||||||
padding: var(--spacing-xs) var(--spacing-md);
|
padding: var(--spacing-xs) var(--spacing-md);
|
||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
border: 2px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
font-size: 0.9375rem;
|
font-size: 0.9375rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -253,7 +253,7 @@ strong {
|
|||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
animation: fadeInUp 0.6s ease 0.4s forwards;
|
animation: fadeInUp 0.6s ease 0.4s forwards;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
border: 3px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
@@ -289,7 +289,7 @@ strong {
|
|||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
transform: rotate(-6deg);
|
transform: rotate(-6deg);
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
border: 3px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-image {
|
.hero-image {
|
||||||
@@ -300,7 +300,7 @@ strong {
|
|||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
border: 3px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.02) rotate(2deg);
|
transform: scale(1.02) rotate(2deg);
|
||||||
@@ -309,7 +309,7 @@ strong {
|
|||||||
|
|
||||||
// FOOTER
|
// FOOTER
|
||||||
.footer {
|
.footer {
|
||||||
border-top: 2px solid var(--color-primary);
|
border-top: 1px solid var(--color-primary);
|
||||||
padding: var(--spacing-lg) 0;
|
padding: var(--spacing-lg) 0;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
}
|
}
|
||||||
@@ -393,7 +393,7 @@ strong {
|
|||||||
gap: var(--spacing-lg);
|
gap: var(--spacing-lg);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-bottom: var(--spacing-lg);
|
padding-bottom: var(--spacing-lg);
|
||||||
border-bottom: 2px solid var(--color-primary);
|
border-bottom: 1px solid var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rates-title-group {
|
.rates-title-group {
|
||||||
@@ -429,7 +429,7 @@ strong {
|
|||||||
gap: var(--spacing-md);
|
gap: var(--spacing-md);
|
||||||
padding: var(--spacing-md) var(--spacing-lg);
|
padding: var(--spacing-md) var(--spacing-lg);
|
||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
border: 3px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
@@ -461,7 +461,7 @@ strong {
|
|||||||
gap: var(--spacing-md);
|
gap: var(--spacing-md);
|
||||||
padding: var(--spacing-lg);
|
padding: var(--spacing-lg);
|
||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
border: 3px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -480,7 +480,7 @@ strong {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.best {
|
&.best {
|
||||||
border-width: 4px;
|
border-width: 2px;
|
||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -492,7 +492,7 @@ strong {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 6px;
|
height: 3px;
|
||||||
background: var(--color-primary);
|
background: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +537,7 @@ strong {
|
|||||||
letter-spacing: 0.75px;
|
letter-spacing: 0.75px;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||||
animation: badgePulse 2s ease-in-out infinite;
|
animation: badgePulse 2s ease-in-out infinite;
|
||||||
border: 2px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '★';
|
content: '★';
|
||||||
@@ -598,7 +598,7 @@ strong {
|
|||||||
gap: var(--spacing-xs);
|
gap: var(--spacing-xs);
|
||||||
padding: var(--spacing-lg);
|
padding: var(--spacing-lg);
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border: 2px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
animation: fadeInUp 0.6s ease 0.4s forwards;
|
animation: fadeInUp 0.6s ease 0.4s forwards;
|
||||||
@@ -700,7 +700,7 @@ strong {
|
|||||||
padding: var(--spacing-sm) var(--spacing-lg);
|
padding: var(--spacing-sm) var(--spacing-lg);
|
||||||
background: var(--color-primary);
|
background: var(--color-primary);
|
||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
border: 3px solid var(--color-primary);
|
border: 1px solid var(--color-primary);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|||||||
Reference in New Issue
Block a user