Light mode
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
|
||||
const pythonCode = `import quantum_entanglement
|
||||
import neural_net_vibes
|
||||
@@ -44,16 +46,26 @@ if __name__ == "__main__":
|
||||
analyzer.check_is_sandwich(target="glizzy")`;
|
||||
|
||||
export default function BlurredCode() {
|
||||
const { resolvedTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setMounted(true), 0);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 overflow-hidden bg-[#0d1117] z-0 pointer-events-none flex justify-center">
|
||||
<div className="relative w-full h-full text-left p-8 opacity-40 blur-[2px] group-hover:blur-none group-hover:opacity-100 transition-all duration-700 animate-[scrollUp_40s_linear_infinite]">
|
||||
<SyntaxHighlighter
|
||||
language="python"
|
||||
style={vscDarkPlus}
|
||||
customStyle={{ background: 'transparent', margin: 0, padding: 0, fontSize: '14px' }}
|
||||
>
|
||||
{pythonCode + '\n\n\n' + pythonCode + '\n\n\n' + pythonCode}
|
||||
</SyntaxHighlighter>
|
||||
<div className="absolute inset-0 overflow-hidden bg-slate-50 dark:bg-[#0d1117] transition-colors duration-300 z-0 pointer-events-none flex justify-center">
|
||||
<div className="relative w-full h-full text-left p-8 opacity-40 blur-[3px] group-hover:blur-[2px] group-hover:opacity-100 transition-all duration-700 animate-[scrollUp_40s_linear_infinite] [&_pre]:bg-transparent! [&_code]:bg-transparent!">
|
||||
{mounted && (
|
||||
<SyntaxHighlighter
|
||||
language="python"
|
||||
style={resolvedTheme === 'light' ? oneLight : oneDark}
|
||||
customStyle={{ margin: 0, padding: 0, fontSize: '14px' }}
|
||||
>
|
||||
{pythonCode + '\n\n\n' + pythonCode + '\n\n\n' + pythonCode}
|
||||
</SyntaxHighlighter>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,23 +2,41 @@
|
||||
|
||||
'use client';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTheme } from 'next-themes';
|
||||
|
||||
interface MatrixRainProps {
|
||||
color?: string;
|
||||
fps?: number;
|
||||
}
|
||||
|
||||
export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainProps) {
|
||||
export default function MatrixRain({ color, fps = 15 }: MatrixRainProps) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const lastWidth = useRef<number>(0);
|
||||
const { resolvedTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setMounted(true), 0);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted) return;
|
||||
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
const isLight = resolvedTheme === 'light';
|
||||
// Use slate-50 (#f8fafc) for light mode, #0d1117 for dark mode
|
||||
const bgColor = isLight ? '#f8fafc' : '#0d1117';
|
||||
// The semi-transparent overlay that creates the fading trail effect
|
||||
const fadeColor = isLight ? 'rgba(248, 250, 252, 0.2)' : 'rgba(13, 17, 23, 0.2)';
|
||||
// A darker green for light mode to maintain contrast, or the default/prop color for dark mode
|
||||
const textColor = color || (isLight ? '#1c2d25' : '#84c0a0');
|
||||
|
||||
const fontSize = 16;
|
||||
let columns = 0;
|
||||
let drops: number[] = [];
|
||||
@@ -26,7 +44,7 @@ export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainPr
|
||||
const setCanvasSize = () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight + 120;
|
||||
ctx.fillStyle = '#0d1117';
|
||||
ctx.fillStyle = bgColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
};
|
||||
|
||||
@@ -43,13 +61,13 @@ export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainPr
|
||||
initDrops();
|
||||
|
||||
const draw = () => {
|
||||
ctx.fillStyle = 'rgba(13, 17, 23, 0.2)';
|
||||
ctx.fillStyle = fadeColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.font = `bold ${fontSize}px monospace`;
|
||||
|
||||
for (let i = 0; i < drops.length; i++) {
|
||||
const text = Math.random() > 0.5 ? '0' : '1';
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillStyle = textColor;
|
||||
ctx.fillText(text, i * fontSize, drops[i] * fontSize);
|
||||
|
||||
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
|
||||
@@ -75,14 +93,16 @@ export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainPr
|
||||
clearInterval(intervalId);
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, [color, fps]);
|
||||
}, [color, fps, resolvedTheme, mounted]); // Re-run effect if theme changes
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 pointer-events-none w-screen h-[110vh] bg-[#0d1117]" style={{ zIndex: -1 }}>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute inset-0 w-full h-full opacity-[0.15] blur-[0.5px]"
|
||||
/>
|
||||
<div className="fixed inset-0 pointer-events-none w-screen h-[110vh] bg-slate-50 dark:bg-[#0d1117] transition-colors duration-300" style={{ zIndex: -1 }}>
|
||||
{mounted && (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute inset-0 w-full h-full opacity-[0.35] dark:opacity-[0.15] blur-[0.5px]"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+36
-14
@@ -3,51 +3,61 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { FaSun, FaMoon } from 'react-icons/fa';
|
||||
|
||||
export default function Navbar() {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const { theme, setTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setMounted(true), 0);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const toggleMenu = () => setIsExpanded(!isExpanded);
|
||||
const closeMenu = () => setIsExpanded(false);
|
||||
|
||||
return (
|
||||
<header className="fixed h-25 bg-[#0d1117]/80 backdrop-blur-md border-b border-white/10 left-0 right-0 z-100 transition-all duration-300">
|
||||
<nav className="flex justify-between h-full items-center max-w-400 px-8 mx-auto">
|
||||
<header className="fixed h-25 bg-white/80 dark:bg-[#0d1117]/80 backdrop-blur-md border-b border-slate-200 dark:border-white/10 left-0 right-0 z-100 transition-colors duration-300">
|
||||
<nav className="flex justify-between h-full items-center max-w-450 px-8 mx-auto">
|
||||
|
||||
<Link href="/" className="group text-white no-underline flex uppercase font-extrabold items-center tracking-[1px] transition-transform hover:scale-105" onClick={closeMenu}>
|
||||
<div className="w-12 h-12 flex justify-center items-center rounded-full bg-[#84c0a0]/10 border border-[#84c0a0]/30 shadow-[0_0_15px_rgba(132,192,160,0.2)] group-hover:bg-[#84c0a0]/20 transition-all duration-300">
|
||||
<Link href="/" className="group text-slate-900 dark:text-white no-underline flex uppercase font-extrabold items-center tracking-[1px] transition-transform hover:scale-105" onClick={closeMenu}>
|
||||
<div className="w-12 h-12 flex justify-center items-center rounded-full bg-[#84c0a0] dark:bg-[#84c0a0]/10 border border-[#84c0a0]/30 shadow-[0_0_15px_rgba(132,192,160,0.2)] group-hover:bg-[#84c0a0]/80 group-hover:dark:bg-[#84c0a0]/20 transition-all duration-300">
|
||||
<Image
|
||||
src="/assets/logos/logo.svg"
|
||||
alt="Wiking"
|
||||
width={32}
|
||||
height={32}
|
||||
className="w-8 h-8 filter dark:invert-0 invert"
|
||||
className="w-8 h-8"
|
||||
/>
|
||||
</div>
|
||||
<span className="hidden md:block ml-4 text-sm tracking-widest text-[#84c0a0] font-mono group-hover:text-white transition-colors">
|
||||
<span className="hidden md:block ml-4 text-sm tracking-widest text-[#84c0a0] font-mono transition">
|
||||
SODERBERG TECH
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="cursor-pointer border-none bg-transparent w-10 h-10 flex items-center justify-center flex-col md:hidden relative group"
|
||||
className="cursor-pointer border-none bg-transparent w-10 h-10 flex items-center justify-center flex-col md:hidden relative group z-50"
|
||||
aria-expanded={isExpanded}
|
||||
onClick={toggleMenu}
|
||||
>
|
||||
<span className={`block h-0.5 bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'opacity-0 w-0' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 -rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-slate-900 dark:bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-slate-900 dark:bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'opacity-0 w-0' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-slate-900 dark:bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 -rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
</button>
|
||||
|
||||
<div
|
||||
className={`fixed top-25 bottom-0 left-0 right-0 transition-all duration-300 md:static md:block md:opacity-100 md:visible md:h-full ${isExpanded ? 'bg-[#0d1117]/60 backdrop-blur-sm opacity-100 visible' : 'opacity-0 invisible'}`}
|
||||
className={`fixed top-25 bottom-0 left-0 right-0 transition-all duration-300 md:static md:block md:opacity-100 md:visible md:h-full ${isExpanded ? 'bg-white/90 dark:bg-[#0d1117]/60 backdrop-blur-sm opacity-100 visible' : 'opacity-0 invisible'}`}
|
||||
onClick={closeMenu}
|
||||
>
|
||||
<ul
|
||||
className={`list-none absolute flex flex-col items-center left-0 right-0 m-4 rounded-3xl bg-[#131920]/70 backdrop-blur-2xl md:backdrop-blur-none border border-white/10 shadow-2xl md:m-0 md:p-0 md:border-none md:shadow-none md:static md:flex-row md:w-full md:h-full md:bg-transparent md:justify-end gap-2 md:gap-8 transition-all duration-300 ${isExpanded ? 'p-8 translate-y-0 opacity-100' : '-translate-y-4 opacity-0 md:translate-y-0 md:opacity-100'}`}
|
||||
// Added md:dark:bg-transparent and md:dark:border-none to clear the mobile dark mode styling on desktop!
|
||||
className={`list-none absolute flex flex-col items-center left-0 right-0 m-4 rounded-3xl bg-white/90 dark:bg-[#0d1117]/90 backdrop-blur-2xl md:backdrop-blur-none border border-slate-200 dark:border-white/10 md:border-none md:dark:border-none shadow-2xl md:m-0 md:p-0 md:shadow-none md:static md:flex-row md:w-full md:h-full md:bg-transparent md:dark:bg-transparent md:justify-end gap-2 md:gap-8 transition-all duration-300 ${isExpanded ? 'p-8 translate-y-0 opacity-100' : '-translate-y-4 opacity-0 md:translate-y-0 md:opacity-100'}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{[
|
||||
@@ -58,7 +68,7 @@ export default function Navbar() {
|
||||
].map((link) => (
|
||||
<li key={link.name} className="w-full md:w-auto">
|
||||
<Link
|
||||
className="relative flex justify-center items-center text-gray-300 uppercase font-bold tracking-[2px] text-sm px-4 py-3 rounded-xl hover:text-white hover:bg-white/5 transition-all duration-300 group overflow-hidden"
|
||||
className="relative flex justify-center items-center text-slate-600 dark:text-gray-300 uppercase font-bold tracking-[2px] text-sm px-4 py-3 rounded-xl hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-white/5 transition-all duration-300 group overflow-hidden"
|
||||
href={link.path}
|
||||
onClick={closeMenu}
|
||||
>
|
||||
@@ -67,6 +77,18 @@ export default function Navbar() {
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
|
||||
<li className="w-full md:w-auto flex justify-center mt-4 md:mt-0 md:pl-2">
|
||||
{mounted && (
|
||||
<button
|
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
||||
className="p-3 md:p-2.5 rounded-full bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white hover:bg-slate-200 dark:hover:bg-white/20 transition-all flex items-center justify-center"
|
||||
aria-label="Toggle Theme"
|
||||
>
|
||||
{theme === 'dark' ? <FaSun size={18} /> : <FaMoon size={18} />}
|
||||
</button>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -15,7 +15,7 @@ interface GalleryImage {
|
||||
|
||||
export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
return (
|
||||
<div className="bg-[#0a0d11] flex justify-center w-full min-h-screen border-t border-white/5">
|
||||
<div className="bg-slate-100 dark:bg-[#0a0d11] flex justify-center w-full min-h-screen border-t border-slate-200 dark:border-white/5 transition-colors duration-300">
|
||||
<Gallery>
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 2xl:grid-cols-6 grid-flow-dense w-full">
|
||||
{images.map((img, index) => {
|
||||
@@ -24,7 +24,7 @@ export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={`relative bg-[#0d1117] overflow-hidden group cursor-pointer border-[0.5px] border-white/5 ${isHorizontal ? 'col-span-2' : 'col-span-1'}`}
|
||||
className={`relative bg-slate-200 dark:bg-[#0d1117] overflow-hidden group cursor-pointer transition-colors duration-300 ${isHorizontal ? 'col-span-2' : 'col-span-1'}`}
|
||||
>
|
||||
<Item
|
||||
original={img.src}
|
||||
@@ -39,8 +39,11 @@ export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
onClick={open}
|
||||
className="w-full h-full relative block min-h-75"
|
||||
>
|
||||
<div className="absolute inset-0 border-8 border-[#0d1117]/50 transition-all duration-300 z-10 pointer-events-none"></div>
|
||||
<div className="absolute inset-4 border-2 border-white/10 transition-all duration-500 z-10 pointer-events-none group-hover:scale-95 group-hover:border-[#84c0a0]/60 [clip-path:polygon(0_calc(100%-1rem),0_100%,1rem_100%,1rem_0,0_0,0_1rem,100%_1rem,100%_0,calc(100%-1rem)_0,calc(100%-1rem)_100%,100%_100%,100%_calc(100%-1rem))]"></div>
|
||||
{/* Outer Frame - Light border in light mode, Dark in dark mode */}
|
||||
<div className="absolute inset-0 border-8 border-slate-100/10 dark:border-[#0d1117]/40 transition-colors duration-300 z-10 pointer-events-none"></div>
|
||||
|
||||
{/* Inner Hover Frame */}
|
||||
<div className="absolute inset-4 border-2 border-slate-300/50 dark:border-white/10 transition-all duration-500 z-10 pointer-events-none group-hover:scale-95 group-hover:border-[#84c0a0]/80 dark:group-hover:border-[#84c0a0]/60 [clip-path:polygon(0_calc(100%-1rem),0_100%,1rem_100%,1rem_0,0_0,0_1rem,100%_1rem,100%_0,calc(100%-1rem)_0,calc(100%-1rem)_100%,100%_100%,100%_calc(100%-1rem))]"></div>
|
||||
|
||||
<Image
|
||||
src={img.src}
|
||||
@@ -49,7 +52,7 @@ export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
height={isHorizontal ? 800 : 800}
|
||||
quality={90}
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
||||
className="w-full h-full object-cover block opacity-80 transition-all duration-700 group-hover:scale-110 group-hover:opacity-100"
|
||||
className="w-full h-full object-cover block transition-all duration-700 group-hover:scale-110 group-hover:opacity-100 dark:group-hover:opacity-100"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// app/components/ThemeProvider.tsx
|
||||
|
||||
'use client';
|
||||
|
||||
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export function ThemeProvider({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<NextThemesProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
{children}
|
||||
</NextThemesProvider>
|
||||
);
|
||||
}
|
||||
+20
-20
@@ -5,7 +5,7 @@ import Image from 'next/image';
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<main className="flex flex-col flex-1 relative bg-[#0d1117] overflow-hidden">
|
||||
<main className="flex flex-col flex-1 relative bg-slate-50 dark:bg-[#0d1117] overflow-hidden transition-colors duration-300">
|
||||
|
||||
{/* 1. Immersive Mountain Background */}
|
||||
<Image
|
||||
@@ -16,14 +16,14 @@ export default function ContactPage() {
|
||||
className="absolute inset-0 w-full h-full object-cover z-0"
|
||||
/>
|
||||
{/* Dark blur overlay so the text and cards remain perfectly readable */}
|
||||
<div className="absolute inset-0 bg-[#0d1117]/85 backdrop-blur-md z-0"></div>
|
||||
<div className="absolute inset-0 bg-slate-100/30 dark:bg-[#0d1117]/85 backdrop-blur-md z-0 transition-colors duration-300"></div>
|
||||
|
||||
<div className="h-25 shrink-0 z-10"></div>
|
||||
|
||||
<section className="relative z-10 flex-1 flex flex-col justify-center items-center py-12 px-6">
|
||||
|
||||
<div className="mb-12 text-center">
|
||||
<h1 className="text-white text-[40px] md:text-[55px] uppercase font-black tracking-tighter drop-shadow-lg">
|
||||
<h1 className="text-slate-900 dark:text-white text-[40px] md:text-[55px] uppercase font-black tracking-tighter drop-shadow-lg transition-colors">
|
||||
Find me here!
|
||||
</h1>
|
||||
<p className="text-[#84c0a0] font-mono font-bold tracking-widest mt-2 uppercase">
|
||||
@@ -31,20 +31,20 @@ export default function ContactPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-3xl bg-white/5 backdrop-blur-xl rounded-4xl border border-white/10 shadow-[0_8px_32px_rgba(0,0,0,0.5)] p-8 md:p-12">
|
||||
<div className="w-full max-w-3xl bg-white/80 dark:bg-white/5 backdrop-blur-xl rounded-4xl border border-slate-200 dark:border-white/10 shadow-xl dark:shadow-[0_8px_32px_rgba(0,0,0,0.5)] p-8 md:p-12 transition-colors duration-300">
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
|
||||
|
||||
<div className="flex flex-col gap-8">
|
||||
<h3 className="text-white text-xl font-bold border-b border-white/10 pb-4 uppercase tracking-wider">Direct Info</h3>
|
||||
<h3 className="text-slate-900 dark:text-white text-xl font-bold border-b border-slate-200 dark:border-white/10 pb-4 uppercase tracking-wider transition-colors">Direct Info</h3>
|
||||
|
||||
<div className="flex items-center gap-4 group">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#84c0a0]/10 flex items-center justify-center border border-[#84c0a0]/30 group-hover:bg-[#84c0a0]/20 transition-all">
|
||||
<FaEnvelope className="text-[#84c0a0] text-xl" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-400 text-xs uppercase font-bold tracking-widest">Email</p>
|
||||
<a href="mailto:support@soderberg.tech" className="text-white font-medium hover:text-[#84c0a0] transition-colors break-all">
|
||||
<p className="text-slate-500 dark:text-gray-400 text-xs uppercase font-bold tracking-widest transition-colors">Email</p>
|
||||
<a href="mailto:support@soderberg.tech" className="text-slate-900 dark:text-white font-medium hover:text-[#84c0a0] dark:hover:text-[#84c0a0] transition-colors break-all">
|
||||
support@soderberg.tech
|
||||
</a>
|
||||
</div>
|
||||
@@ -55,35 +55,35 @@ export default function ContactPage() {
|
||||
<FaMapMarkerAlt className="text-[#84c0a0] text-xl" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-400 text-xs uppercase font-bold tracking-widest">Location</p>
|
||||
<p className="text-white font-medium">Höganäs, Sweden</p>
|
||||
<p className="text-slate-500 dark:text-gray-400 text-xs uppercase font-bold tracking-widest transition-colors">Location</p>
|
||||
<p className="text-slate-900 dark:text-white font-medium transition-colors">Höganäs, Sweden</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<h3 className="text-white text-xl font-bold border-b border-white/10 pb-4 uppercase tracking-wider">Networks</h3>
|
||||
<h3 className="text-slate-900 dark:text-white text-xl font-bold border-b border-slate-200 dark:border-white/10 pb-4 uppercase tracking-wider transition-colors">Networks</h3>
|
||||
|
||||
<div className="grid grid-cols-1 gap-3">
|
||||
<a href="https://www.linkedin.com/in/william-s%C3%B6derberg-5b79bb247" target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/5 border border-white/5 hover:border-[#0077b5]/50 hover:bg-[#0077b5]/10 transition-all group">
|
||||
<div className="flex items-center gap-3 text-white font-bold">
|
||||
<a href="https://www.linkedin.com/in/william-s%C3%B6derberg-5b79bb247" target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/50 dark:bg-white/5 border border-slate-200 dark:border-white/5 hover:border-[#0077b5]/50 hover:bg-[#0077b5]/10 transition-all group">
|
||||
<div className="flex items-center gap-3 text-slate-900 dark:text-white font-bold transition-colors">
|
||||
<FaLinkedin className="text-xl text-[#0077b5]" /> LinkedIn
|
||||
</div>
|
||||
<span className="text-gray-500 group-hover:text-[#0077b5] group-hover:translate-x-1 transition-all">→</span>
|
||||
<span className="text-slate-400 dark:text-gray-500 group-hover:text-[#0077b5] group-hover:translate-x-1 transition-all">→</span>
|
||||
</a>
|
||||
|
||||
<a href="https://discordapp.com/users/271290165106966528" target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/5 border border-white/5 hover:border-[#5865F2]/50 hover:bg-[#5865F2]/10 transition-all group">
|
||||
<div className="flex items-center gap-3 text-white font-bold">
|
||||
<a href="https://discordapp.com/users/271290165106966528" target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/50 dark:bg-white/5 border border-slate-200 dark:border-white/5 hover:border-[#5865F2]/50 hover:bg-[#5865F2]/10 transition-all group">
|
||||
<div className="flex items-center gap-3 text-slate-900 dark:text-white font-bold transition-colors">
|
||||
<FaDiscord className="text-xl text-[#5865F2]" /> Discord
|
||||
</div>
|
||||
<span className="text-gray-500 group-hover:text-[#5865F2] group-hover:translate-x-1 transition-all">→</span>
|
||||
<span className="text-slate-400 dark:text-gray-500 group-hover:text-[#5865F2] group-hover:translate-x-1 transition-all">→</span>
|
||||
</a>
|
||||
|
||||
<a href="https://www.instagram.com/will.i.am.soderberg/" target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/5 border border-white/5 hover:border-[#E1306C]/50 hover:bg-[#E1306C]/10 transition-all group">
|
||||
<div className="flex items-center gap-3 text-white font-bold">
|
||||
<a href="https://www.instagram.com/will.i.am.soderberg/" target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/50 dark:bg-white/5 border border-slate-200 dark:border-white/5 hover:border-[#E1306C]/50 hover:bg-[#E1306C]/10 transition-all group">
|
||||
<div className="flex items-center gap-3 text-slate-900 dark:text-white font-bold transition-colors">
|
||||
<FaInstagram className="text-xl text-[#E1306C]" /> Instagram
|
||||
</div>
|
||||
<span className="text-gray-500 group-hover:text-[#E1306C] group-hover:translate-x-1 transition-all">→</span>
|
||||
<span className="text-slate-400 dark:text-gray-500 group-hover:text-[#E1306C] group-hover:translate-x-1 transition-all">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,7 +92,7 @@ export default function ContactPage() {
|
||||
<div className="mt-12">
|
||||
<a
|
||||
href="mailto:support@soderberg.tech?subject=Contact%20me"
|
||||
className="w-full flex items-center justify-center gap-3 py-5 rounded-2xl bg-[#84c0a0] text-[#0d1117] font-bold text-lg hover:scale-[1.02] active:scale-[0.98] transition-all shadow-[0_0_20px_rgba(132,192,160,0.3)]"
|
||||
className="w-full flex items-center justify-center gap-3 py-5 rounded-2xl bg-[#84c0a0] text-white dark:text-[#0d1117] font-bold text-lg hover:scale-[1.02] active:scale-[0.98] transition-all shadow-[0_0_20px_rgba(132,192,160,0.3)]"
|
||||
>
|
||||
<FaEnvelope /> Send an Email
|
||||
</a>
|
||||
|
||||
@@ -30,7 +30,7 @@ export default async function GalleryPage() {
|
||||
const images = await getImages();
|
||||
|
||||
return (
|
||||
<main className="flex flex-col flex-1 relative bg-[#0d1117] overflow-hidden">
|
||||
<main className="flex flex-col flex-1 relative bg-slate-50 dark:bg-[#0d1117] overflow-hidden transition-colors duration-300">
|
||||
|
||||
{/* 1. Background Ambient Glow */}
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-150 h-150 bg-[#84c0a0]/10 blur-[150px] rounded-full pointer-events-none z-0"></div>
|
||||
@@ -40,8 +40,8 @@ export default async function GalleryPage() {
|
||||
{/* 2. Modernized Header */}
|
||||
<section className="relative z-10 flex flex-col justify-center items-center py-20 px-6">
|
||||
<div className="text-center">
|
||||
<h1 className="text-white text-[40px] md:text-[55px] uppercase font-black tracking-tighter drop-shadow-lg mb-4">
|
||||
Visual Archives
|
||||
<h1 className="text-slate-900 dark:text-white text-[40px] md:text-[55px] uppercase font-black tracking-tighter drop-shadow-lg mb-4 transition-colors">
|
||||
Gallery
|
||||
</h1>
|
||||
|
||||
<div className="flex items-center justify-center gap-4 mb-6">
|
||||
@@ -52,8 +52,8 @@ export default async function GalleryPage() {
|
||||
<div className="w-12 h-px bg-[#84c0a0]"></div>
|
||||
</div>
|
||||
|
||||
<p className="text-gray-400 font-light max-w-2xl mx-auto text-lg leading-relaxed">
|
||||
A curated collection of photographic captures. Finding the best subjects to capture on film, from natural landscapes to the night sky.
|
||||
<p className="text-slate-600 dark:text-gray-400 font-light max-w-2xl mx-auto text-lg leading-relaxed transition-colors">
|
||||
A curated collection of photograps. Finding the best subjects to capture, from natural landscapes to the night sky.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
@import "tailwindcss";
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@keyframes zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
|
||||
+19
-21
@@ -1,8 +1,9 @@
|
||||
// app/layout.tsx
|
||||
|
||||
import Navbar from './components/Navbar';
|
||||
import './globals.css';
|
||||
import Link from 'next/link';
|
||||
import Navbar from './components/Navbar';
|
||||
import { ThemeProvider } from './components/ThemeProvider';
|
||||
import './globals.css';
|
||||
|
||||
export const metadata = {
|
||||
title: 'Soderberg Tech',
|
||||
@@ -12,30 +13,27 @@ export const metadata = {
|
||||
shortcut: '/assets/logos/logo.svg',
|
||||
apple: '/assets/logos/logo.svg',
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className="flex flex-col min-h-screen m-0 p-0 font-sans bg-[#0d1117]">
|
||||
<Navbar />
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body className="flex flex-col min-h-screen m-0 p-0 font-sans bg-slate-50 dark:bg-[#0d1117] transition-colors duration-300">
|
||||
<ThemeProvider>
|
||||
<Navbar />
|
||||
|
||||
<main className="flex flex-col flex-1">
|
||||
{children}
|
||||
</main>
|
||||
<main className="flex flex-col flex-1">
|
||||
{children}
|
||||
</main>
|
||||
|
||||
<footer className="w-full relative z-50 mt-auto border-t border-white/5">
|
||||
<div className="bg-[#0d1117] flex justify-center items-center h-10">
|
||||
<Link className="text-[#a0aab6] no-underline flex font-medium items-center hover:text-white transition-colors text-sm tracking-widest uppercase" href="/">
|
||||
© William Söderberg {new Date().getFullYear()}
|
||||
</Link>
|
||||
</div>
|
||||
</footer>
|
||||
<footer className="w-full relative z-50 mt-auto border-t border-slate-200 dark:border-white/5 transition-colors duration-300">
|
||||
<div className="bg-slate-100 dark:bg-[#0d1117] flex justify-center items-center h-10 transition-colors duration-300">
|
||||
<Link className="text-slate-500 dark:text-[#a0aab6] no-underline flex font-medium items-center hover:text-slate-900 dark:hover:text-white transition-colors text-sm tracking-widest uppercase" href="/">
|
||||
© William Söderberg {new Date().getFullYear()}
|
||||
</Link>
|
||||
</div>
|
||||
</footer>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
+51
-86
@@ -8,29 +8,24 @@ import { TbCube3dSphere } from 'react-icons/tb';
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function Home() {
|
||||
|
||||
const calculateAge = (birthDateString: string): number => {
|
||||
const today = new Date();
|
||||
const birthDate = new Date(birthDateString);
|
||||
|
||||
let age = today.getFullYear() - birthDate.getFullYear();
|
||||
const monthDiff = today.getMonth() - birthDate.getMonth();
|
||||
|
||||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||
age--;
|
||||
}
|
||||
|
||||
return age;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative w-full bg-[#0d1117] text-white overflow-hidden font-sans">
|
||||
<div className="relative w-full bg-slate-50 dark:bg-[#0d1117] text-slate-900 dark:text-white overflow-hidden font-sans transition-colors duration-300">
|
||||
|
||||
{/* 1. HERO SECTION */}
|
||||
<section className="relative h-screen min-h-175 flex flex-col justify-center items-center overflow-hidden">
|
||||
|
||||
{/* Ambient Overlay for contrast */}
|
||||
<div className="absolute inset-0 bg-linear-to-b from-transparent via-[#0d1117]/50 to-[#0d1117] z-1"></div>
|
||||
<div className="absolute inset-0 bg-linear-to-b from-transparent via-slate-50/50 to-slate-50 dark:via-[#0d1117]/50 dark:to-[#0d1117] z-1 transition-colors duration-300"></div>
|
||||
|
||||
<div className="relative z-10 flex flex-col items-center px-4">
|
||||
<div className="bg-[#84c0a0] rounded-full h-45 w-45 md:h-55 md:w-55 flex justify-center items-center shadow-[0_0_50px_rgba(132,192,160,0.3)] animate-[zoomIn_1000ms_ease-out]">
|
||||
@@ -40,12 +35,12 @@ export default function Home() {
|
||||
<h2 className="text-[#84c0a0] font-mono font-bold tracking-[0.3em] uppercase mt-12 text-sm md:text-xl text-center">
|
||||
Technical High School Engineer
|
||||
</h2>
|
||||
<h1 className="text-white text-center uppercase text-[3rem] md:text-[6rem] font-black leading-none mt-4 drop-shadow-2xl">
|
||||
<h1 className="text-slate-900 dark:text-white text-center uppercase text-[3rem] md:text-[6rem] font-black leading-none mt-4 drop-shadow-lg dark:drop-shadow-2xl transition-colors">
|
||||
William Söderberg
|
||||
</h1>
|
||||
|
||||
<div className="mt-10 flex gap-4">
|
||||
<Link href="/projects" className="bg-[#84c0a0] text-[#0d1117] px-8 py-3 rounded-full font-bold uppercase tracking-wider hover:scale-105 transition-transform shadow-lg">
|
||||
<Link href="/projects" className="bg-[#84c0a0] text-white dark:text-[#0d1117] px-8 py-3 rounded-full font-bold uppercase tracking-wider hover:scale-105 transition-transform shadow-lg">
|
||||
View Portfolios
|
||||
</Link>
|
||||
</div>
|
||||
@@ -54,51 +49,42 @@ export default function Home() {
|
||||
|
||||
{/* 2. ABOUT ME SECTION */}
|
||||
<section className="relative py-24 px-6">
|
||||
{/* Background Glow */}
|
||||
<div className="absolute top-1/2 left-0 -translate-y-1/2 w-125 h-125 bg-[#84c0a0]/5 blur-[120px] rounded-full pointer-events-none"></div>
|
||||
<div className="absolute top-1/2 left-0 -translate-y-1/2 w-125 h-125 bg-[#84c0a0]/10 dark:bg-[#84c0a0]/5 blur-[120px] rounded-full pointer-events-none"></div>
|
||||
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Subtitle Header */}
|
||||
<div className="max-w-6xl mx-auto relative z-10">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-white text-4xl md:text-5xl font-black uppercase tracking-tighter">About Me</h2>
|
||||
<h2 className="text-slate-900 dark:text-white text-4xl md:text-5xl font-black uppercase tracking-tighter transition-colors">About Me</h2>
|
||||
<p className="text-[#84c0a0] mt-4 font-mono uppercase text-sm tracking-widest font-bold">Identity & Background</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/5 backdrop-blur-xl border border-white/10 rounded-[40px] overflow-hidden flex flex-col lg:flex-row shadow-2xl">
|
||||
|
||||
{/* Left Column: Profile with "Scanning" Effect */}
|
||||
<div className="lg:w-2/5 relative group border-b lg:border-b-0 lg:border-r border-white/10">
|
||||
<Image
|
||||
src="/assets/images/profile_picture.jpg"
|
||||
alt="William Söderberg"
|
||||
width={800}
|
||||
height={1000}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-linear-to-t from-[#0d1117] via-transparent to-transparent opacity-60"></div>
|
||||
<div className="bg-white/80 dark:bg-white/5 backdrop-blur-xl border border-slate-200 dark:border-white/10 rounded-[40px] overflow-hidden flex flex-col lg:flex-row shadow-xl dark:shadow-2xl transition-colors duration-300">
|
||||
<div className="lg:w-2/5 relative group border-b lg:border-b-0 lg:border-r border-slate-200 dark:border-white/10">
|
||||
<Image src="/assets/images/profile_picture.jpg" alt="William Söderberg" width={800} height={1000} className="w-full h-full object-cover" />
|
||||
<div className="absolute inset-0 bg-linear-to-t from-black/80 dark:from-[#0d1117] via-transparent to-transparent opacity-60"></div>
|
||||
<div className="absolute bottom-8 left-8">
|
||||
<h3 className="text-white text-2xl font-bold uppercase tracking-tight">William Söderberg</h3>
|
||||
<p className="text-[#84c0a0] font-mono text-sm mt-1">EST. 2002 | SWEDEN</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Bio Content */}
|
||||
<div className="lg:w-3/5 p-8 md:p-16 flex flex-col justify-center">
|
||||
<div className="flex items-center gap-4 mb-8">
|
||||
<div className="w-12 h-1 border-t-2 border-[#84c0a0]"></div>
|
||||
<h2 className="text-white text-3xl font-bold uppercase tracking-widest">DATA CARD</h2>
|
||||
<h2 className="text-slate-900 dark:text-white text-3xl font-bold uppercase tracking-widest transition-colors">DATA CARD</h2>
|
||||
</div>
|
||||
<p className="text-gray-300 text-lg leading-relaxed font-light">
|
||||
My name is William Söderberg and I'm {calculateAge("2002-07-17")} years old. I have a degree in technical high school engineering specialized in design and industrial manufacturing, with heavy influence from IT and coding. I love problem solving and finding new ways to solve the most complicated problems.
|
||||
<p className="text-slate-600 dark:text-gray-300 text-lg leading-relaxed font-light transition-colors">
|
||||
My name is William Söderberg and I'm {calculateAge("2002-07-17")} years old. I have a degree in technical
|
||||
high school engineering specialized in design and industrial manufacturing, with heavy influence from IT and coding.
|
||||
I love problem solving and finding new ways to solve the most complicated problems. Currently studying Computer Science at LTH in Lund.
|
||||
</p>
|
||||
<div className="mt-10 grid grid-cols-2 gap-6 border-t border-white/10 pt-10">
|
||||
<div className="mt-10 grid grid-cols-2 gap-6 border-t border-slate-200 dark:border-white/10 pt-10 transition-colors">
|
||||
<div>
|
||||
<p className="text-xs font-bold text-[#84c0a0] uppercase tracking-widest mb-1">Focus</p>
|
||||
<p className="text-white font-medium text-sm">Industrial Design & IT</p>
|
||||
<p className="text-slate-900 dark:text-white font-medium text-sm transition-colors">Industrial Design & IT</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-[#84c0a0] uppercase tracking-widest mb-1">Passions</p>
|
||||
<p className="text-white font-medium text-sm">Volleyball & Computers</p>
|
||||
<p className="text-slate-900 dark:text-white font-medium text-sm transition-colors">Volleyball & Computers</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,28 +94,27 @@ export default function Home() {
|
||||
|
||||
{/* 3. WHAT DO I DO SECTION */}
|
||||
<section className="relative py-24 px-6 overflow-hidden">
|
||||
{/* Subtle Background Image Integration */}
|
||||
<Image src="/assets/images/leaves.jpg" alt="Leaves" fill className="object-cover z-0" />
|
||||
<div className="absolute inset-0 bg-[#0d1117]/50 z-0"></div>
|
||||
<Image src="/assets/images/leaves.jpg" alt="Leaves" fill className="object-cover z-0 opacity-80" />
|
||||
<div className="absolute inset-0 bg-slate-50/20 dark:bg-[#0d1117]/50 z-0 transition-colors duration-300"></div>
|
||||
|
||||
<div className="relative z-10 max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-white text-4xl md:text-5xl font-black uppercase tracking-tighter">What do I do?</h2>
|
||||
<h2 className="text-slate-900 dark:text-white text-4xl md:text-5xl font-black uppercase tracking-tighter transition-colors">What do I do?</h2>
|
||||
<p className="text-[#84c0a0] mt-4 font-mono uppercase text-sm tracking-widest font-bold">A multidisciplinary engineer</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="flex flex-wrap justify-center gap-6">
|
||||
{[
|
||||
{ icon: <FaVolleyballBall />, title: 'Volleyball', desc: 'Played for over 5 years as a middle blocker with Lerbergets and Ängelholms clubs.' },
|
||||
{ icon: <FaVolleyballBall />, title: 'Volleyball', desc: '8 Years going strong! Currently playing middle blocker with the Elite team in Lund. Mother club is Lerbergets volleybollsällskap.' },
|
||||
{ icon: <FaTree />, title: 'Young Ranger', desc: 'Part of the Youth+ Network at Europarc Federation, working in management at Kullaberg.' },
|
||||
{ icon: <FaCamera />, title: 'Photography', desc: 'Capturing nature and people, finding the best subjects on film.' },
|
||||
{ icon: <FaCamera />, title: 'Photography', desc: 'Capturing nature and people, finding the best subjects to save.' },
|
||||
{ icon: <TbCube3dSphere />, title: 'CAD', desc: 'Specialized in design and manufacturing, modeling everything from concepts to architecture.' },
|
||||
{ icon: <FaCode />, title: 'Coding', desc: 'Developing automation scripts and custom programs to solve unique problems.' }
|
||||
{ icon: <FaCode />, title: 'Coding', desc: 'Developing automation scripts and custom programs to solve unique problems. Check out my portfolio!' }
|
||||
].map((item, idx) => (
|
||||
<div key={idx} className="group p-8 rounded-3xl bg-white/5 backdrop-blur-md border border-white/10 hover:border-[#84c0a0]/40 hover:bg-white/10 transition-all duration-300">
|
||||
<div className="text-[#84c0a0] text-4xl mb-6 w-fit group-hover:scale-110 transition-transform duration-300">{item.icon}</div>
|
||||
<h3 className="text-white text-2xl font-bold mb-4">{item.title}</h3>
|
||||
<p className="text-gray-400 text-sm leading-relaxed">{item.desc}</p>
|
||||
<div key={idx} className="w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)] group p-8 rounded-3xl bg-white/30 dark:bg-white/5 backdrop-blur-md border border-slate-200 dark:border-white/10 hover:border-[#84c0a0]/40 dark:hover:border-[#84c0a0]/40 hover:bg-white/90 dark:hover:bg-white/10 transition-all duration-300 shadow-md dark:shadow-none">
|
||||
<div className="text-slate-900 dark:text-[#84c0a0] text-4xl mb-6 w-fit group-hover:scale-110 transition-transform duration-300">{item.icon}</div>
|
||||
<h3 className="text-slate-900 dark:text-white text-2xl font-bold mb-4 transition-colors">{item.title}</h3>
|
||||
<p className="text-slate-600 dark:text-gray-400 text-sm leading-relaxed transition-colors">{item.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -137,44 +122,39 @@ export default function Home() {
|
||||
</section>
|
||||
|
||||
{/* 4. PHOTO GALLERY SECTION */}
|
||||
<section className="py-24 px-6 bg-[#0d1117]">
|
||||
<section className="py-24 px-6 bg-slate-100 dark:bg-[#0d1117] transition-colors duration-300 border-t border-slate-200 dark:border-transparent">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-white text-4xl md:text-5xl font-black uppercase tracking-tighter">Photography</h2>
|
||||
<h2 className="text-slate-900 dark:text-white text-4xl md:text-5xl font-black uppercase tracking-tighter transition-colors">Photography</h2>
|
||||
<p className="text-[#84c0a0] mt-4 font-mono uppercase text-sm tracking-widest font-bold">Capturing the world</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col lg:flex-row items-center lg:items-start gap-12 lg:gap-16">
|
||||
|
||||
{/* My Photos (Ynni Image) */}
|
||||
<div className="relative w-full lg:w-1/2">
|
||||
<Image src="/assets/images/ynni.jpg" alt="My Photos" width={800} height={800} className="w-full rounded-4xl shadow-2xl object-cover lg:h-125" />
|
||||
<div className="absolute top-[10%] -left-4 lg:-left-12 bg-white/10 backdrop-blur-xl border border-white/20 py-6 px-10 shadow-2xl rounded-2xl">
|
||||
<h2 className="text-[30px] lg:text-[40px] text-white font-black whitespace-nowrap uppercase tracking-wider">My Photos</h2>
|
||||
<Image src="/assets/images/ynni.jpg" alt="My Photos" quality={90} width={800} height={1000} className="w-full rounded-4xl shadow-2xl object-cover lg:h-150" />
|
||||
<div className="absolute top-[10%] -left-4 lg:-left-12 bg-white/20 dark:bg-white/10 backdrop-blur-xl border border-[#84c0a0]/40 dark:border-white/20 py-6 px-10 shadow-2xl rounded-2xl">
|
||||
<h2 className="text-[30px] lg:text-[40px] text-slate-900 dark:text-white font-black whitespace-nowrap uppercase tracking-wider transition-colors">My Photos</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Night Sky Collection */}
|
||||
<div className="flex flex-col items-start w-full lg:w-1/2 lg:pt-8">
|
||||
<Image src="/assets/images/night_sky.jpg" alt="Night Sky" width={600} height={400} className="w-full max-w-125 rounded-3xl shadow-xl border border-gray-200 dark:border-white/10" />
|
||||
<h3 className="text-white text-[26px] mt-8 font-bold uppercase tracking-wide">My Photography collection</h3>
|
||||
<Image src="/assets/images/night_sky.jpg" alt="Night Sky" width={600} height={400} className="w-full max-w-125 rounded-3xl shadow-xl border border-slate-200 dark:border-white/10" />
|
||||
<h3 className="text-slate-900 dark:text-white text-[26px] mt-8 font-bold uppercase tracking-wide transition-colors">My Photography collection</h3>
|
||||
<div className="w-12 h-1 border-t-2 border-[#84c0a0] my-4"></div>
|
||||
<p className="text-gray-400 text-[18px] font-light leading-relaxed">
|
||||
Taking photos is just one of my many hobbies. Finding the best subjects to capture on film, from nature to the night skies.
|
||||
<p className="text-slate-600 dark:text-gray-400 text-[18px] font-light leading-relaxed transition-colors">
|
||||
Taking photos is just one of my many hobbies. Finding the best motives to capture, from nature to the night skies.
|
||||
</p>
|
||||
<Link href="/gallery" className="mt-8 bg-[#84c0a0] text-[#0d1117] px-8 py-3 rounded-full font-bold uppercase tracking-wider hover:scale-105 transition-transform shadow-[0_0_20px_rgba(132,192,160,0.3)]">
|
||||
<Link href="/gallery" className="mt-8 bg-[#84c0a0] text-white dark:text-[#0d1117] px-8 py-3 rounded-full font-bold uppercase tracking-wider hover:scale-105 transition-transform shadow-[0_0_20px_rgba(132,192,160,0.3)]">
|
||||
More photos
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Singapore Full Width wrapper */}
|
||||
<div className="w-full mt-32 relative h-125 md:h-175 rounded-[40px] overflow-hidden shadow-2xl border border-white/10 group">
|
||||
<div className="w-full mt-32 relative h-125 md:h-175 rounded-[40px] overflow-hidden shadow-2xl border border-slate-200 dark:border-white/10 group">
|
||||
<Image src="/assets/images/singapore.jpg" alt="Singapore" fill className="object-cover transition-transform duration-1000 group-hover:scale-105" />
|
||||
<div className="absolute inset-0 bg-linear-to-t from-[#0d1117]/90 via-[#0d1117]/20 to-transparent"></div>
|
||||
|
||||
<div className="absolute inset-0 bg-linear-to-t from-black/80 dark:from-[#0d1117]/90 via-black/20 dark:via-[#0d1117]/20 to-transparent"></div>
|
||||
<div className="relative z-10 w-full h-full p-8 md:p-16 flex items-end md:items-start">
|
||||
<div className="bg-[#0d1117]/30 backdrop-blur-xl border border-white/10 p-8 max-w-87.5 rounded-3xl shadow-2xl">
|
||||
<div className="bg-[#0d1117]/30 backdrop-blur-xl border border-white/20 dark:border-white/10 p-8 max-w-87.5 rounded-3xl shadow-2xl">
|
||||
<p className="text-[18px] font-medium text-white leading-relaxed">
|
||||
A cloudy day in Singapore, the New Zealand trip 2019.
|
||||
</p>
|
||||
@@ -188,38 +168,23 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 5. CONTACT CALL-TO-ACTION (Compact Banner) */}
|
||||
<section className="relative py-16 px-6 overflow-hidden border-t border-white/5">
|
||||
{/* Immersive Mountain Background */}
|
||||
<Image
|
||||
src="/assets/images/snowy_mountain_peaks.jpg"
|
||||
alt="Snowy Mountains"
|
||||
fill
|
||||
className="object-cover z-0"
|
||||
/>
|
||||
|
||||
{/* Dark overlay */}
|
||||
<div className="absolute inset-0 bg-[#0d1117]/80 backdrop-blur-[2px] z-0"></div>
|
||||
|
||||
{/* Compact Glassmorphic CTA Banner */}
|
||||
<div className="relative z-10 max-w-5xl mx-auto bg-white/5 backdrop-blur-xl border border-white/10 rounded-3xl p-8 md:px-12 md:py-10 shadow-2xl flex flex-col md:flex-row items-center justify-between gap-6">
|
||||
{/* 5. CONTACT CALL-TO-ACTION */}
|
||||
<section className="relative py-16 px-6 overflow-hidden border-t border-slate-200 dark:border-white/5 transition-colors duration-300">
|
||||
<Image src="/assets/images/snowy_mountain_peaks.jpg" alt="Snowy Mountains" fill className="object-cover z-0" />
|
||||
<div className="absolute inset-0 bg-slate-100/40 dark:bg-[#0d1117]/80 backdrop-blur-[2px] z-0 transition-colors duration-300"></div>
|
||||
|
||||
<div className="relative z-10 max-w-5xl mx-auto bg-white/70 dark:bg-white/5 backdrop-blur-xl border border-slate-200 dark:border-white/10 rounded-3xl p-8 md:px-12 md:py-10 shadow-xl dark:shadow-2xl flex flex-col md:flex-row items-center justify-between gap-6 transition-colors duration-300">
|
||||
<div className="text-center md:text-left">
|
||||
<h2 className="text-white text-3xl md:text-4xl font-black uppercase tracking-tighter mb-2">
|
||||
<h2 className="text-slate-900 dark:text-white text-3xl md:text-4xl font-black uppercase tracking-tighter mb-2 transition-colors">
|
||||
Let's Connect
|
||||
</h2>
|
||||
<p className="text-[#84c0a0] font-mono uppercase text-xs md:text-sm tracking-widest font-bold">
|
||||
Transmission & Socials
|
||||
Contact info & Socials
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/contact"
|
||||
className="shrink-0 inline-block bg-[#84c0a0] text-[#0d1117] px-8 py-4 rounded-full font-bold uppercase tracking-wider hover:scale-105 active:scale-95 transition-all shadow-[0_0_20px_rgba(132,192,160,0.3)]"
|
||||
>
|
||||
<Link href="/contact" className="shrink-0 inline-block bg-[#84c0a0] text-white dark:text-[#0d1117] px-8 py-4 rounded-full font-bold uppercase tracking-wider hover:scale-105 active:scale-95 transition-all shadow-[0_0_20px_rgba(132,192,160,0.3)]">
|
||||
Contact Me
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
+42
-41
@@ -107,7 +107,7 @@ export default async function CodePage() {
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="flex flex-col flex-1 relative min-h-dvh">
|
||||
<main className="flex flex-col flex-1 relative min-h-dvh bg-slate-50/50 dark:bg-transparent transition-colors duration-300">
|
||||
<MatrixRain />
|
||||
|
||||
<div className="h-25 shrink-0"></div>
|
||||
@@ -117,35 +117,35 @@ export default async function CodePage() {
|
||||
{/* 2. Profile Card Section */}
|
||||
{profile && (
|
||||
<section className="flex justify-center mt-10">
|
||||
<div className="relative flex flex-col justify-center items-center bg-linear-to-b from-[#333333]/90 to-[#2a2a2a]/90 backdrop-blur-lg rounded-3xl text-center p-8 shadow-[0_8px_32px_rgba(0,0,0,0.5)] w-full max-w-md border border-white/10">
|
||||
<div className="relative flex flex-col justify-center items-center bg-white/90 dark:bg-linear-to-b dark:from-[#333333]/90 dark:to-[#2a2a2a]/90 backdrop-blur-lg rounded-3xl text-center p-8 shadow-xl dark:shadow-[0_8px_32px_rgba(0,0,0,0.5)] w-full max-w-md border border-slate-200 dark:border-white/10 transition-colors duration-300">
|
||||
<a href={profile.html_url} target="_blank" rel="noopener noreferrer">
|
||||
<FaGithub className="absolute text-white text-[28px] top-5 right-5 hover:text-[#84c0a0] transition-colors" />
|
||||
<FaGithub className="absolute text-slate-800 dark:text-white text-[28px] top-5 right-5 hover:text-[#84c0a0] dark:hover:text-[#84c0a0] transition-colors" />
|
||||
</a>
|
||||
<div className="w-full">
|
||||
<div className="relative h-37.5 w-37.5 mx-auto mb-5">
|
||||
<Image src={profile.avatar_url} alt="Avatar" width={150} height={150} className="h-full w-full rounded-full object-cover border-4 border-[#58806a] dark:border-[#84c0a0] shadow-[0_0_15px_rgba(88,128,106,0.3)] dark:shadow-[0_0_15px_rgba(132,192,160,0.5)]" />
|
||||
<Image src={profile.avatar_url} alt="Avatar" width={150} height={150} className="h-full w-full rounded-full object-cover border-4 border-[#84c0a0]/50 dark:border-[#84c0a0] shadow-[0_0_15px_rgba(132,192,160,0.3)] dark:shadow-[0_0_15px_rgba(132,192,160,0.5)]" />
|
||||
</div>
|
||||
<h1 className="mb-1">
|
||||
<a className="text-white text-[26px] font-bold tracking-wide no-underline hover:text-[#84c0a0] transition-colors" href={profile.html_url} target="_blank" rel="noopener noreferrer">
|
||||
<a className="text-slate-900 dark:text-white text-[26px] font-bold tracking-wide no-underline hover:text-[#84c0a0] dark:hover:text-[#84c0a0] transition-colors" href={profile.html_url} target="_blank" rel="noopener noreferrer">
|
||||
{profile.name}
|
||||
</a>
|
||||
</h1>
|
||||
<div className="mb-5">
|
||||
<a className="text-[#a0aab6] font-medium no-underline hover:text-white transition-colors" href={profile.html_url} target="_blank" rel="noopener noreferrer">
|
||||
<a className="text-slate-500 dark:text-[#a0aab6] font-medium no-underline hover:text-slate-800 dark:hover:text-white transition-colors" href={profile.html_url} target="_blank" rel="noopener noreferrer">
|
||||
@{profile.login}
|
||||
</a>
|
||||
</div>
|
||||
<p className="font-medium mx-auto text-[#84c0a0] mt-2.5 text-[15px] leading-relaxed">
|
||||
{profile.bio}
|
||||
</p>
|
||||
<div className="mt-8 relative border-t border-white/10 pt-5 flex justify-around">
|
||||
<div className="mt-8 relative border-t border-slate-200 dark:border-white/10 pt-5 flex justify-around transition-colors duration-300">
|
||||
<div className="relative">
|
||||
<div className="text-white text-[22px] font-bold">{profile.followers}</div>
|
||||
<div className="text-[11px] font-bold text-[#a0aab6] tracking-widest uppercase mt-1">Followers</div>
|
||||
<div className="text-slate-900 dark:text-white text-[22px] font-bold transition-colors">{profile.followers}</div>
|
||||
<div className="text-[11px] font-bold text-slate-500 dark:text-[#a0aab6] tracking-widest uppercase mt-1 transition-colors">Followers</div>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="text-white text-[22px] font-bold">{profile.public_repos}</div>
|
||||
<div className="text-[11px] font-bold text-[#a0aab6] tracking-widest uppercase mt-1">Repositories</div>
|
||||
<div className="text-slate-900 dark:text-white text-[22px] font-bold transition-colors">{profile.public_repos}</div>
|
||||
<div className="text-[11px] font-bold text-slate-500 dark:text-[#a0aab6] tracking-widest uppercase mt-1 transition-colors">Repositories</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,35 +154,34 @@ export default async function CodePage() {
|
||||
)}
|
||||
|
||||
{/* 3. GitLab Repositories Section */}
|
||||
<section className="bg-[#fc6d26]/10 backdrop-blur-lg rounded-3xl border border-[#fc6d26]/30 p-8 shadow-2xl">
|
||||
<section className="bg-[#fc6d26]/15 dark:bg-[#fc6d26]/10 backdrop-blur-lg rounded-3xl border border-[#fc6d26]/20 dark:border-[#fc6d26]/30 p-8 shadow-xl dark:shadow-2xl transition-colors duration-300">
|
||||
<div className="flex justify-center items-center flex-col mb-10">
|
||||
<a href="https://gitlab.soderberg.tech/WilliamSoderberg" target="_blank" rel="noopener noreferrer">
|
||||
<FaGitlab className="text-[#fc6d26] text-[55px] drop-shadow-[0_0_15px_rgba(252,109,38,0.4)] hover:scale-110 transition-transform cursor-pointer" />
|
||||
</a>
|
||||
<h2 className="text-white mt-3.75 text-[32px] md:text-[38px] uppercase font-bold text-center tracking-wider">
|
||||
<h2 className="text-slate-900 dark:text-white mt-3.75 text-[32px] md:text-[38px] uppercase font-bold text-center tracking-wider transition-colors">
|
||||
GitLab Projects
|
||||
</h2>
|
||||
<p className="text-gray-300 text-center max-w-2xl mt-3">Self-hosted infrastructure and private development.</p>
|
||||
<p className="text-slate-600 dark:text-gray-300 text-center max-w-2xl mt-3 transition-colors">Self-hosted infrastructure and private development.</p>
|
||||
</div>
|
||||
|
||||
{gitlabRepos.length > 0 ? (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 justify-center">
|
||||
{gitlabRepos.map((repo) => (
|
||||
<a key={repo.id} href={repo.web_url} target="_blank" rel="noopener noreferrer" className="group flex flex-col justify-between bg-linear-to-br from-[#2a2a2a]/90 to-[#222222]/90 border border-white/10 p-6 rounded-2xl hover:-translate-y-1 hover:border-[#fc6d26]/60 hover:shadow-[0_8px_24px_rgba(252,109,38,0.2)] transition-all duration-300 no-underline">
|
||||
<a key={repo.id} href={repo.web_url} target="_blank" rel="noopener noreferrer" className="group flex flex-col justify-between bg-white/90 dark:bg-linear-to-br dark:from-[#2a2a2a]/90 dark:to-[#222222]/90 border border-slate-200 dark:border-white/10 p-6 rounded-2xl hover:-translate-y-1 hover:border-[#fc6d26]/60 dark:hover:border-[#fc6d26]/60 hover:shadow-[0_8px_24px_rgba(252,109,38,0.15)] dark:hover:shadow-[0_8px_24px_rgba(252,109,38,0.2)] transition-all duration-300 no-underline">
|
||||
<div>
|
||||
<h3 className="text-[#fc6d26] text-[19px] font-bold group-hover:text-white transition-colors truncate">
|
||||
<h3 className="text-[#fc6d26] text-[19px] font-bold group-hover:text-slate-900 dark:group-hover:text-white transition-colors truncate">
|
||||
{repo.name}
|
||||
</h3>
|
||||
<p className="text-[14px] mb-4 mt-2.5 text-gray-400 text-left line-clamp-3 leading-relaxed">
|
||||
<p className="text-[14px] mb-4 mt-2.5 text-slate-500 dark:text-gray-400 text-left line-clamp-3 leading-relaxed transition-colors">
|
||||
{repo.description || 'No description provided.'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center text-[13px] text-[#8b949e] mt-4 font-medium">
|
||||
{/* NEW: GitLab Language Badge */}
|
||||
<div className="flex items-center text-[13px] text-slate-500 dark:text-[#8b949e] mt-4 font-medium transition-colors">
|
||||
{repo.language && (
|
||||
<div className="flex items-center mr-5">
|
||||
<span className={`w-2.5 h-2.5 rounded-full mr-2 ${langColors[repo.language] || 'bg-gray-500'}`}></span>
|
||||
<span className="text-gray-300">{repo.language}</span>
|
||||
<span className="text-slate-600 dark:text-gray-300">{repo.language}</span>
|
||||
</div>
|
||||
)}
|
||||
{repo.star_count > 0 && (
|
||||
@@ -200,35 +199,35 @@ export default async function CodePage() {
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center text-gray-400 italic py-8 bg-black/20 rounded-xl">No public GitLab repositories found or API is restricted.</div>
|
||||
<div className="text-center text-slate-500 dark:text-gray-400 italic py-8 bg-black/5 dark:bg-black/20 rounded-xl transition-colors">No public GitLab repositories found or API is restricted.</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* 4. GitHub Repositories Section */}
|
||||
<section className="bg-[#84c0a0]/10 backdrop-blur-lg rounded-3xl border border-[#84c0a0]/30 p-8 shadow-2xl">
|
||||
<section className="bg-[#84c0a0]/15 dark:bg-[#84c0a0]/10 backdrop-blur-lg rounded-3xl border border-[#84c0a0]/20 dark:border-[#84c0a0]/30 p-8 shadow-xl dark:shadow-2xl transition-colors duration-300">
|
||||
<div className="flex justify-center items-center flex-col mb-10">
|
||||
<FaGithub className="text-white text-[55px] drop-shadow-[0_0_15px_rgba(255,255,255,0.2)]" />
|
||||
<h2 className="text-white mt-3.75 text-[32px] md:text-[38px] uppercase font-bold text-center tracking-wider">
|
||||
<FaGithub className="text-slate-900 dark:text-white text-[55px] drop-shadow-md dark:drop-shadow-[0_0_15px_rgba(255,255,255,0.2)] transition-colors" />
|
||||
<h2 className="text-slate-900 dark:text-white mt-3.75 text-[32px] md:text-[38px] uppercase font-bold text-center tracking-wider transition-colors">
|
||||
Public Repositories
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 justify-center">
|
||||
{githubRepos.map((repo) => (
|
||||
<a key={repo.id} href={repo.html_url} target="_blank" rel="noopener noreferrer" className="group flex flex-col justify-between bg-linear-to-br from-[#2a2a2a]/90 to-[#222222]/90 border border-white/10 p-6 rounded-2xl hover:-translate-y-1 hover:border-[#84c0a0]/60 hover:shadow-[0_8px_24px_rgba(132,192,160,0.2)] transition-all duration-300 no-underline">
|
||||
<a key={repo.id} href={repo.html_url} target="_blank" rel="noopener noreferrer" className="group flex flex-col justify-between bg-white/90 dark:bg-linear-to-br dark:from-[#2a2a2a]/90 dark:to-[#222222]/90 border border-slate-200 dark:border-white/10 p-6 rounded-2xl hover:-translate-y-1 hover:border-[#84c0a0]/60 hover:shadow-[0_8px_24px_rgba(132,192,160,0.15)] dark:hover:shadow-[0_8px_24px_rgba(132,192,160,0.2)] transition-all duration-300 no-underline">
|
||||
<div>
|
||||
<h3 className="text-[#4e9fff] text-[19px] font-bold group-hover:text-white transition-colors truncate">
|
||||
<h3 className="text-[#4e9fff] text-[19px] font-bold group-hover:text-slate-900 dark:group-hover:text-white transition-colors truncate">
|
||||
{repo.name}
|
||||
</h3>
|
||||
<p className="text-[14px] mb-4 mt-2.5 text-gray-400 text-left line-clamp-3 leading-relaxed">
|
||||
<p className="text-[14px] mb-4 mt-2.5 text-slate-500 dark:text-gray-400 text-left line-clamp-3 leading-relaxed transition-colors">
|
||||
{repo.description || 'No description provided.'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center text-[13px] text-[#8b949e] mt-4 font-medium">
|
||||
<div className="flex items-center text-[13px] text-slate-500 dark:text-[#8b949e] mt-4 font-medium transition-colors">
|
||||
{repo.language && (
|
||||
<div className="flex items-center mr-5">
|
||||
<span className={`w-2.5 h-2.5 rounded-full mr-2 ${langColors[repo.language] || 'bg-gray-500'}`}></span>
|
||||
<span className="text-gray-300">{repo.language}</span>
|
||||
<span className="text-slate-600 dark:text-gray-300">{repo.language}</span>
|
||||
</div>
|
||||
)}
|
||||
{repo.stargazers_count > 0 && (
|
||||
@@ -248,31 +247,33 @@ export default async function CodePage() {
|
||||
</section>
|
||||
|
||||
{/* 5. Hosted Websites Section */}
|
||||
<section className="bg-white/5 backdrop-blur-lg rounded-3xl border border-white/10 p-10 shadow-2xl">
|
||||
<section className="bg-white/80 dark:bg-white/5 backdrop-blur-lg rounded-3xl border border-slate-200 dark:border-white/10 p-10 shadow-xl dark:shadow-2xl transition-colors duration-300">
|
||||
<div className="flex justify-center items-center flex-col mb-10">
|
||||
<FaGlobe className="text-white text-[55px] drop-shadow-[0_0_15px_rgba(255,255,255,0.2)]" />
|
||||
<h2 className="text-white mt-3.75 text-[32px] md:text-[38px] uppercase font-bold text-center tracking-wider">
|
||||
<FaGlobe className="text-slate-900 dark:text-white text-[55px] drop-shadow-md dark:drop-shadow-[0_0_15px_rgba(255,255,255,0.2)] transition-colors" />
|
||||
<h2 className="text-slate-900 dark:text-white mt-3.75 text-[32px] md:text-[38px] uppercase font-bold text-center tracking-wider transition-colors">
|
||||
Hosted Websites
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Changed from Flex to Grid for perfect centering! */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-12 max-w-5xl mx-auto justify-items-center items-center py-6">
|
||||
<a className="no-underline text-gray-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://soderberg.tech">
|
||||
<Image src="/assets/logos/logo.svg" alt="Soderberg Tech" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-[0_0_10px_rgba(0,0,0,0.2)] dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<div className="flex flex-wrap justify-center gap-12 max-w-5xl mx-auto py-6">
|
||||
<a className="w-full md:w-[calc(33.333%-32px)] no-underline text-slate-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://soderberg.tech">
|
||||
<Image src="/assets/logos/logo.svg" alt="Soderberg Tech" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-lg dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<span className="font-bold tracking-wide text-center">Soderberg Tech</span>
|
||||
</a>
|
||||
<a className="no-underline text-gray-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://lirkab.se">
|
||||
<Image src="/assets/logos/lirkab.svg" alt="Lirkab" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-[0_0_10px_rgba(0,0,0,0.2)] dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<a className="w-full md:w-[calc(33.333%-32px)] no-underline text-slate-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://lirkab.se">
|
||||
<Image src="/assets/logos/lirkab.svg" alt="Lirkab" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-lg dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<span className="font-bold tracking-wide text-center">Lirkab</span>
|
||||
</a>
|
||||
<a className="no-underline text-gray-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://lerbergetsvolleyboll.se">
|
||||
<Image src="/assets/logos/lvs.svg" alt="Lerbergets Volleyboll" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-[0_0_10px_rgba(0,0,0,0.2)] dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<a className="w-full md:w-[calc(33.333%-32px)] no-underline text-slate-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://lerbergetsvolleyboll.se">
|
||||
<Image src="/assets/logos/lvs.svg" alt="Lerbergets Volleyboll" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-lg dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<span className="font-bold tracking-wide text-center">Lerbergets Volleyboll</span>
|
||||
</a>
|
||||
<a className="w-full md:w-[calc(33.333%-32px)] no-underline text-slate-900 dark:text-white text-[22px] flex flex-col items-center hover:scale-105 transition-transform group" href="https://naturvardarna.com">
|
||||
<Image src="/assets/logos/naturvardarna.svg" alt="Naturvärdarna Kullaberg" width={90} height={65} className="w-22.5 h-16.25 object-contain mb-5 drop-shadow-md group-hover:drop-shadow-lg dark:group-hover:drop-shadow-[0_0_10px_rgba(255,255,255,0.5)] transition-all dark:invert-0 filter invert" />
|
||||
<span className="font-bold tracking-wide text-center">Naturvärdarna Kullaberg</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
@@ -60,22 +60,30 @@ export default function DesignPage() {
|
||||
const showOverlay = isPending || !isSceneReady;
|
||||
|
||||
return (
|
||||
<main className="flex flex-col flex-1 relative bg-[#0d1117] overflow-hidden">
|
||||
<main className="flex flex-col flex-1 relative bg-slate-50 dark:bg-[#0d1117] overflow-hidden transition-colors duration-300">
|
||||
{/* Background Glow */}
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-200 h-200 bg-[#84c0a0]/10 blur-[150px] rounded-full pointer-events-none z-0"></div>
|
||||
<div className="h-25 shrink-0"></div>
|
||||
|
||||
<div className="relative z-10 w-full max-w-350 mx-auto px-4 pb-20 flex flex-col gap-10">
|
||||
<div className="pt-5 flex justify-center items-center flex-col text-center">
|
||||
<TbCube3dSphere className="text-white text-[80px] drop-shadow-[0_0_15px_rgba(255,255,255,0.2)]" />
|
||||
<h2 className="text-white text-[32px] md:text-[45px] uppercase mt-3.75 font-bold tracking-wider">CAD Library</h2>
|
||||
{/* Changed from flex-col to lg:flex-row for side-by-side layout on desktop */}
|
||||
<div className="relative z-10 w-full max-w-450 mx-auto px-4 lg:px-12 pb-20 flex flex-col lg:flex-row gap-10 lg:gap-16 items-center lg:items-start pt-10">
|
||||
|
||||
{/* 1. Title Section (Now on the left and sticky!) */}
|
||||
<div className="w-full lg:w-1/3 flex flex-col justify-center items-center lg:items-start text-center lg:text-left pt-5 lg:sticky lg:top-40">
|
||||
<TbCube3dSphere className="text-slate-900 dark:text-white text-[80px] drop-shadow-md dark:drop-shadow-[0_0_15px_rgba(255,255,255,0.2)] transition-colors" />
|
||||
<h2 className="text-slate-900 dark:text-white text-[32px] md:text-[45px] uppercase mt-4 font-bold tracking-wider transition-colors leading-tight">CAD Library</h2>
|
||||
<p className="text-slate-500 dark:text-gray-400 mt-4 text-base md:text-lg leading-relaxed transition-colors">
|
||||
Explore my 3D modeling and design work. Interact with the models using your mouse or touch screen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section className="w-full flex justify-center">
|
||||
<div className="w-full relative bg-white/5 backdrop-blur-xl rounded-4xl border border-white/10 shadow-[0_8px_32px_rgba(0,0,0,0.5)] p-4 md:p-8 flex flex-col">
|
||||
<div className="w-full h-[50vh] md:h-[65vh] rounded-[20px] overflow-hidden relative bg-linear-to-br from-[#1a1a1a] to-[#0f0f0f] shadow-inner border border-white/5 cursor-grab active:cursor-grabbing">
|
||||
{/* 2. Viewer Section (Now taking up the right side) */}
|
||||
<section className="w-full lg:w-2/3 flex justify-center">
|
||||
<div className="w-full relative bg-white/80 dark:bg-white/5 backdrop-blur-xl rounded-4xl border border-slate-200 dark:border-white/10 shadow-xl dark:shadow-[0_8px_32px_rgba(0,0,0,0.5)] p-4 md:p-8 flex flex-col transition-colors duration-300">
|
||||
<div className="w-full h-[50vh] md:h-[60vh] rounded-[20px] overflow-hidden relative bg-slate-200 dark:bg-linear-to-br dark:from-[#1a1a1a] dark:to-[#0f0f0f] shadow-inner border border-slate-300 dark:border-white/5 cursor-grab active:cursor-grabbing transition-colors duration-300">
|
||||
|
||||
{showOverlay && (
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-[#0d1117]/80 backdrop-blur-md transition-all duration-500">
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-slate-100/80 dark:bg-[#0d1117]/80 backdrop-blur-md transition-all duration-500">
|
||||
<div className="w-12 h-12 border-4 border-[#84c0a0]/20 border-t-[#84c0a0] rounded-full animate-spin mb-4"></div>
|
||||
<p className="text-[#84c0a0] font-mono text-xs uppercase tracking-[0.2em] font-bold">
|
||||
{isPending ? "Fetching Data..." : "Compiling Materials..."}
|
||||
@@ -122,7 +130,7 @@ export default function DesignPage() {
|
||||
innerStyles={{ display: 'none' }}
|
||||
/>
|
||||
|
||||
<a href={`/models/${activeModel}.usdz`} rel="ar" className="absolute top-4 right-4 bg-black/50 backdrop-blur-md text-white text-sm px-4 py-2 rounded-full border border-white/10 hover:bg-white/20 transition-colors md:hidden z-10 flex items-center gap-2">
|
||||
<a href={`/models/${activeModel}.usdz`} rel="ar" className="absolute top-4 right-4 bg-white/80 dark:bg-black/50 text-slate-900 dark:text-white backdrop-blur-md text-sm px-4 py-2 rounded-full border border-slate-300 dark:border-white/10 hover:bg-slate-100 dark:hover:bg-white/20 transition-colors md:hidden z-10 flex items-center gap-2">
|
||||
<Image
|
||||
src={`/models/${activeModel}.png`}
|
||||
alt="AR Preview"
|
||||
@@ -140,15 +148,15 @@ export default function DesignPage() {
|
||||
<button
|
||||
key={model.name}
|
||||
className={`shrink-0 w-20 h-20 md:w-25 md:h-25 bg-contain bg-no-repeat bg-center rounded-2xl transition-all duration-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#84c0a0] relative group ${activeModel === model.src
|
||||
? 'bg-[#2a2a2a] border-2 border-[#84c0a0] scale-110 shadow-[0_0_20px_rgba(132,192,160,0.3)]'
|
||||
: 'bg-[#1a1a1a] border border-white/10 hover:bg-[#252525] hover:-translate-y-1'
|
||||
? 'bg-white dark:bg-[#2a2a2a] border-2 border-[#84c0a0] scale-110 shadow-[0_0_20px_rgba(132,192,160,0.3)]'
|
||||
: 'bg-slate-100 dark:bg-[#1a1a1a] border border-slate-200 dark:border-white/10 hover:bg-slate-200 dark:hover:bg-[#252525] hover:-translate-y-1'
|
||||
}`}
|
||||
style={{ backgroundImage: `url('/models/${model.src}.png')` }}
|
||||
onClick={() => handleModelChange(model.src)}
|
||||
onMouseEnter={() => useGLTF.preload(`/models/${model.src}.glb`)}
|
||||
aria-label={`View ${model.name} model`}
|
||||
>
|
||||
<span className="absolute -bottom-8 left-1/2 -translate-x-1/2 text-xs font-semibold text-white opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap bg-black/80 px-2 py-1 rounded">
|
||||
<span className="absolute -bottom-8 left-1/2 -translate-x-1/2 text-xs font-semibold text-white opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap bg-slate-800/90 dark:bg-black/80 px-2 py-1 rounded">
|
||||
{model.name}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
+11
-11
@@ -7,17 +7,17 @@ import { FaCode } from 'react-icons/fa';
|
||||
|
||||
export default function ProjectsPage() {
|
||||
return (
|
||||
<main className="flex flex-col flex-1 relative bg-[#0d1117] overflow-x-hidden">
|
||||
<main className="flex flex-col flex-1 relative bg-slate-50 dark:bg-[#0d1117] overflow-x-hidden transition-colors duration-300">
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-150 md:w-250 h-150 md:h-250 bg-[#84c0a0]/10 blur-[150px] rounded-full pointer-events-none z-0"></div>
|
||||
|
||||
<div className="h-25 shrink-0"></div>
|
||||
|
||||
<div className="relative z-10 flex-1 flex flex-col justify-center items-center py-10 md:py-20 px-6">
|
||||
<div className="mb-12 text-center">
|
||||
<h1 className="text-white text-[32px] md:text-[55px] uppercase font-extrabold tracking-wider drop-shadow-lg">
|
||||
<h1 className="text-slate-900 dark:text-white text-[32px] md:text-[55px] uppercase font-extrabold tracking-wider drop-shadow-lg transition-colors">
|
||||
My Portfolios
|
||||
</h1>
|
||||
<p className="text-[#a0aab6] mt-2 text-base md:text-xl max-w-md mx-auto">
|
||||
<p className="text-slate-600 dark:text-[#a0aab6] mt-2 text-base md:text-xl max-w-md mx-auto transition-colors">
|
||||
Choose a discipline to explore my work.
|
||||
</p>
|
||||
</div>
|
||||
@@ -26,12 +26,12 @@ export default function ProjectsPage() {
|
||||
|
||||
<Link
|
||||
href="/projects/code"
|
||||
className="relative flex-1 group min-h-75 md:h-125 rounded-4xl overflow-hidden border border-white/10 shadow-[0_8px_32px_rgba(0,0,0,0.5)] transition-all duration-500 hover:-translate-y-2 hover:border-[#84c0a0]/60 no-underline"
|
||||
className="relative flex-1 group min-h-75 md:h-125 rounded-4xl overflow-hidden border border-slate-300 dark:border-white/10 shadow-xl dark:shadow-[0_8px_32px_rgba(0,0,0,0.5)] transition-all duration-500 hover:-translate-y-2 hover:border-[#84c0a0]/60 no-underline"
|
||||
>
|
||||
<BlurredCode />
|
||||
<div className="absolute inset-0 z-10 bg-[#0d1117]/60 backdrop-blur-[2px] group-hover:bg-[#0d1117]/20 group-hover:backdrop-blur-[1px] transition-all duration-500 flex flex-col justify-center items-center p-8">
|
||||
<FaCode className="text-white text-[50px] md:text-[80px] mb-4 md:mb-6 opacity-80 group-hover:opacity-100 group-hover:scale-110 group-hover:text-[#84c0a0] transition-all duration-500" />
|
||||
<h2 className="text-white text-[32px] md:text-[50px] font-bold text-center tracking-wide">
|
||||
<div className="absolute inset-0 z-10 bg-slate-50/10 dark:bg-[#0d1117]/60 backdrop-blur-[1px] group-hover:bg-slate-50/20 dark:group-hover:bg-[#0d1117]/20 group-hover:backdrop-blur-[2px] transition-all duration-500 flex flex-col justify-center items-center p-8">
|
||||
<FaCode className="text-slate-900 dark:text-white text-[50px] md:text-[80px] mb-4 md:mb-6 opacity-80 group-hover:opacity-100 group-hover:scale-110 group-hover:text-[#84c0a0] dark:group-hover:text-[#84c0a0] transition-all duration-500" />
|
||||
<h2 className="text-slate-900 dark:text-white text-[32px] md:text-[50px] font-bold text-center tracking-wide transition-colors">
|
||||
Coding
|
||||
</h2>
|
||||
</div>
|
||||
@@ -39,16 +39,16 @@ export default function ProjectsPage() {
|
||||
|
||||
<Link
|
||||
href="/projects/design"
|
||||
className="relative flex-1 group min-h-75 md:h-125 rounded-4xl overflow-hidden border border-white/10 shadow-[0_8px_32px_rgba(0,0,0,0.5)] transition-all duration-500 hover:-translate-y-2 hover:border-[#84c0a0]/60 no-underline"
|
||||
className="relative flex-1 group min-h-75 md:h-125 rounded-4xl overflow-hidden border border-slate-300 dark:border-white/10 shadow-xl dark:shadow-[0_8px_32px_rgba(0,0,0,0.5)] transition-all duration-500 hover:-translate-y-2 hover:border-[#84c0a0]/60 no-underline"
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 z-0 bg-center bg-cover bg-no-repeat opacity-40 group-hover:opacity-100 group-hover:scale-105 transition-all duration-700"
|
||||
style={{ backgroundImage: `url('/assets/images/CAD.png')` }}
|
||||
></div>
|
||||
|
||||
<div className="absolute inset-0 z-10 bg-[#0d1117]/60 backdrop-blur-[2px] group-hover:bg-[#0d1117]/20 group-hover:backdrop-blur-[1px] transition-all duration-500 flex flex-col justify-center items-center p-8">
|
||||
<TbCube3dSphere className="text-white text-[50px] md:text-[80px] mb-4 md:mb-6 opacity-80 group-hover:opacity-100 group-hover:scale-110 group-hover:text-[#84c0a0] transition-all duration-500" />
|
||||
<h2 className="text-white text-[32px] md:text-[50px] font-bold text-center tracking-wide">
|
||||
<div className="absolute inset-0 z-10 bg-slate-50/10 dark:bg-[#0d1117]/60 backdrop-blur-[3px] group-hover:bg-slate-50/20 dark:group-hover:bg-[#0d1117]/20 group-hover:backdrop-blur-[2px] transition-all duration-500 flex flex-col justify-center items-center p-8">
|
||||
<TbCube3dSphere className="text-slate-900 dark:text-white text-[50px] md:text-[80px] mb-4 md:mb-6 opacity-80 group-hover:opacity-100 group-hover:scale-110 group-hover:text-[#84c0a0] dark:group-hover:text-[#84c0a0] transition-all duration-500" />
|
||||
<h2 className="text-slate-900 dark:text-white text-[32px] md:text-[50px] font-bold text-center tracking-wide transition-colors">
|
||||
CAD & Design
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user