Compare commits

..

No commits in common. "4736c2dd0cae6754a37c1a147a4e7f69f43ec1de" and "dc215c89f4d2c83d6c392c66aebdf23b83512d75" have entirely different histories.

20 changed files with 414 additions and 709 deletions

View File

@ -36,12 +36,12 @@ const isFeatured = variant === 'featured';
--- ---
<article class:list={[ <article class:list={[
'group relative border border-[var(--theme-border-primary)] bg-[var(--theme-hover-bg)] hover:border-brand-accent/40 transition-all duration-500 overflow-hidden', 'group relative border border-white/10 bg-white/[0.02] hover:border-brand-accent/40 transition-all duration-500 overflow-hidden',
isFeatured ? 'lg:grid lg:grid-cols-2' : '', isFeatured ? 'lg:grid lg:grid-cols-2' : '',
className className
]}> ]}>
<!-- Accent indicator strip --> <!-- Accent indicator strip -->
<div class="absolute top-0 left-0 w-1 h-full bg-[var(--theme-text-subtle)] opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div> <div class="absolute top-0 left-0 w-1 h-full bg-slate-700 opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div>
<!-- Image section --> <!-- Image section -->
<a href={href} class:list={[ <a href={href} class:list={[
@ -57,13 +57,13 @@ const isFeatured = variant === 'featured';
class="w-full h-full object-cover transition-transform duration-[1.2s] ease-out group-hover:scale-105" class="w-full h-full object-cover transition-transform duration-[1.2s] ease-out group-hover:scale-105"
/> />
)} )}
<div class="absolute inset-0 bg-[var(--theme-card-overlay)] group-hover:opacity-50 transition-opacity duration-500"></div> <div class="absolute inset-0 bg-brand-dark/40 group-hover:bg-brand-dark/20 transition-colors duration-500"></div>
<div class="absolute inset-0 bg-gradient-to-t from-[var(--theme-card-gradient)] to-transparent"></div> <div class="absolute inset-0 bg-gradient-to-t from-brand-dark/60 to-transparent"></div>
<!-- Category badge overlay --> <!-- Category badge overlay -->
{category && ( {category && (
<div class="absolute top-4 left-4"> <div class="absolute top-4 left-4">
<span class="px-3 py-1.5 text-[10px] font-mono font-bold uppercase tracking-widest bg-[var(--theme-bg-primary)]/80 border border-[var(--theme-border-strong)] text-[var(--theme-text-primary)] backdrop-blur-sm"> <span class="px-3 py-1.5 text-[10px] font-mono font-bold uppercase tracking-widest bg-brand-dark/80 border border-white/20 text-white backdrop-blur-sm">
{category} {category}
</span> </span>
</div> </div>
@ -80,8 +80,8 @@ const isFeatured = variant === 'featured';
<span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest"> <span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest">
<FormattedDate date={pubDate} /> <FormattedDate date={pubDate} />
</span> </span>
<span class="h-px flex-grow max-w-8 bg-[var(--theme-border-strong)]"></span> <span class="h-px flex-grow max-w-8 bg-white/20"></span>
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest">
{readTime} {readTime}
</span> </span>
</div> </div>
@ -89,7 +89,7 @@ const isFeatured = variant === 'featured';
<!-- Title --> <!-- Title -->
<a href={href}> <a href={href}>
<h3 class:list={[ <h3 class:list={[
'font-bold text-[var(--theme-text-primary)] uppercase tracking-tight mb-3 group-hover:text-brand-accent transition-colors duration-300 leading-tight', 'font-bold text-white uppercase tracking-tight mb-3 group-hover:text-brand-accent transition-colors duration-300 leading-tight',
isFeatured ? 'text-3xl lg:text-4xl' : isCompact ? 'text-lg' : 'text-xl lg:text-2xl' isFeatured ? 'text-3xl lg:text-4xl' : isCompact ? 'text-lg' : 'text-xl lg:text-2xl'
]}> ]}>
{title} {title}
@ -98,7 +98,7 @@ const isFeatured = variant === 'featured';
<!-- Description --> <!-- Description -->
<p class:list={[ <p class:list={[
'text-[var(--theme-text-secondary)] font-light leading-relaxed', 'text-slate-400 font-light leading-relaxed',
isFeatured ? 'text-base lg:text-lg line-clamp-3 mb-8' : isCompact ? 'text-sm line-clamp-2 mb-4' : 'text-sm line-clamp-2 mb-6' isFeatured ? 'text-base lg:text-lg line-clamp-3 mb-8' : isCompact ? 'text-sm line-clamp-2 mb-4' : 'text-sm line-clamp-2 mb-6'
]}> ]}>
{description} {description}
@ -108,7 +108,7 @@ const isFeatured = variant === 'featured';
{tags && tags.length > 0 && !isCompact && ( {tags && tags.length > 0 && !isCompact && (
<div class="flex flex-wrap gap-2 mb-6"> <div class="flex flex-wrap gap-2 mb-6">
{tags.slice(0, 4).map((tag) => ( {tags.slice(0, 4).map((tag) => (
<span class="px-2 py-1 text-[10px] font-mono uppercase border border-[var(--theme-border-primary)] text-[var(--theme-text-muted)] group-hover:border-[var(--theme-border-strong)] transition-colors"> <span class="px-2 py-1 text-[10px] font-mono uppercase border border-white/10 text-slate-500 group-hover:border-white/20 transition-colors">
{tag} {tag}
</span> </span>
))} ))}
@ -118,14 +118,14 @@ const isFeatured = variant === 'featured';
<!-- Read link --> <!-- Read link -->
<div class:list={[ <div class:list={[
'flex items-center', 'flex items-center',
isFeatured ? 'mt-auto pt-6 border-t border-[var(--theme-border-primary)]' : 'mt-auto' isFeatured ? 'mt-auto pt-6 border-t border-white/10' : 'mt-auto'
]}> ]}>
<a <a
href={href} href={href}
class="inline-flex items-center gap-3 text-xs font-bold uppercase tracking-widest text-[var(--theme-text-muted)] group-hover:text-[var(--theme-text-primary)] transition-all duration-300" class="inline-flex items-center gap-3 text-xs font-bold uppercase tracking-widest text-slate-500 group-hover:text-white transition-all duration-300"
> >
Read Article Read Article
<span class="block w-6 h-[1px] bg-[var(--theme-text-subtle)] group-hover:bg-brand-accent group-hover:w-10 transition-all duration-300"></span> <span class="block w-6 h-[1px] bg-slate-600 group-hover:bg-brand-accent group-hover:w-10 transition-all duration-300"></span>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="12" width="12"
@ -145,3 +145,4 @@ const isFeatured = variant === 'featured';
</div> </div>
</div> </div>
</article> </article>

View File

@ -12,13 +12,13 @@ const { categories, class: className = '' } = Astro.props;
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-6 mb-10"> <div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-6 mb-10">
<!-- Category chips --> <!-- Category chips -->
<div class="flex flex-wrap items-center gap-1"> <div class="flex flex-wrap items-center gap-1">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest mr-4"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest mr-4">
/// SECTOR SELECT /// SECTOR SELECT
</span> </span>
<button <button
type="button" type="button"
data-category="all" data-category="all"
class="filter-chip active px-4 py-2 text-[10px] font-mono font-bold uppercase tracking-widest border-b-2 border-brand-accent text-[var(--theme-text-primary)] bg-[var(--theme-hover-bg-strong)] transition-all duration-300 hover:bg-[var(--theme-hover-bg-strong)]" class="filter-chip active px-4 py-2 text-[10px] font-mono font-bold uppercase tracking-widest border-b-2 border-brand-accent text-white bg-white/5 transition-all duration-300 hover:bg-white/10"
> >
All All
</button> </button>
@ -26,7 +26,7 @@ const { categories, class: className = '' } = Astro.props;
<button <button
type="button" type="button"
data-category={category} data-category={category}
class="filter-chip px-4 py-2 text-[10px] font-mono font-bold uppercase tracking-widest border-b-2 border-transparent text-[var(--theme-text-muted)] hover:text-[var(--theme-text-primary)] hover:border-brand-accent/50 hover:bg-[var(--theme-hover-bg-strong)] transition-all duration-300" class="filter-chip px-4 py-2 text-[10px] font-mono font-bold uppercase tracking-widest border-b-2 border-transparent text-slate-500 hover:text-white hover:border-brand-accent/50 hover:bg-white/5 transition-all duration-300"
> >
{category} {category}
</button> </button>
@ -42,12 +42,12 @@ const { categories, class: className = '' } = Astro.props;
type="text" type="text"
id="blog-search" id="blog-search"
placeholder="SEARCH_DATABASE..." placeholder="SEARCH_DATABASE..."
class="w-full pl-6 pr-4 py-2 text-sm font-mono bg-transparent border-b border-[var(--theme-text-subtle)] text-[var(--theme-text-primary)] placeholder:text-[var(--theme-text-subtle)] focus:border-brand-accent focus:outline-none transition-colors duration-300 uppercase" class="w-full pl-6 pr-4 py-2 text-sm font-mono bg-transparent border-b border-slate-700 text-white placeholder:text-slate-600 focus:border-brand-accent focus:outline-none transition-colors duration-300 uppercase"
/> />
<button <button
type="button" type="button"
id="clear-search" id="clear-search"
class="absolute right-0 top-1/2 -translate-y-1/2 text-[var(--theme-text-muted)] hover:text-brand-accent transition-colors hidden" class="absolute right-0 top-1/2 -translate-y-1/2 text-slate-500 hover:text-brand-accent transition-colors hidden"
> >
<span class="font-mono text-xs">[CLR]</span> <span class="font-mono text-xs">[CLR]</span>
</button> </button>
@ -55,11 +55,11 @@ const { categories, class: className = '' } = Astro.props;
</div> </div>
<!-- Results count --> <!-- Results count -->
<div class="flex items-center gap-4 pb-6 border-b border-[var(--theme-border-primary)] mb-8"> <div class="flex items-center gap-4 pb-6 border-b border-white/10 mb-8">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest">
<span id="results-count">0</span> ARTICLES <span id="results-count">0</span> ARTICLES
</span> </span>
<span class="h-px flex-grow bg-[var(--theme-border-secondary)]"></span> <span class="h-px flex-grow bg-white/5"></span>
</div> </div>
</div> </div>
@ -122,13 +122,13 @@ const { categories, class: className = '' } = Astro.props;
// Update active state // Update active state
// Reset all to inactive state // Reset all to inactive state
filterChips.forEach((c) => { filterChips.forEach((c) => {
c.classList.remove('active', 'border-brand-accent', 'text-[var(--theme-text-primary)]', 'bg-[var(--theme-hover-bg-strong)]'); c.classList.remove('active', 'border-brand-accent', 'text-white', 'bg-white/5');
c.classList.add('border-transparent', 'text-[var(--theme-text-muted)]'); c.classList.add('border-transparent', 'text-slate-500');
}); });
// Set clicked to active state // Set clicked to active state
chipEl.classList.add('active', 'border-brand-accent', 'text-[var(--theme-text-primary)]', 'bg-[var(--theme-hover-bg-strong)]'); chipEl.classList.add('active', 'border-brand-accent', 'text-white', 'bg-white/5');
chipEl.classList.remove('border-transparent', 'text-[var(--theme-text-muted)]'); chipEl.classList.remove('border-transparent', 'text-slate-500');
filterPosts(); filterPosts();
}); });
@ -173,7 +173,8 @@ const { categories, class: className = '' } = Astro.props;
<style> <style>
.filter-chip.active { .filter-chip.active {
border-color: var(--color-brand-accent); border-color: var(--color-brand-accent);
color: var(--theme-text-primary); color: white;
background-color: var(--theme-hover-bg-strong); background-color: rgba(255, 77, 0, 0.05);
} }
</style> </style>

View File

@ -2,10 +2,10 @@
const today = new Date(); const today = new Date();
--- ---
<footer class="container mx-auto px-6 lg:px-12 py-32 lg:py-40 relative overflow-hidden border-t border-[var(--theme-border-secondary)]"> <footer class="container mx-auto px-6 lg:px-12 py-32 lg:py-40 relative overflow-hidden border-t border-white/5">
<div class="grid grid-cols-1 md:grid-cols-2 gap-16 lg:gap-24 items-end relative z-10"> <div class="grid grid-cols-1 md:grid-cols-2 gap-16 lg:gap-24 items-end relative z-10">
<div class="animate-on-scroll slide-right"> <div class="animate-on-scroll slide-right">
<h2 class="text-5xl md:text-7xl lg:text-8xl font-bold uppercase leading-[0.95] tracking-tighter mb-10 text-[var(--theme-text-primary)] group cursor-pointer"> <h2 class="text-5xl md:text-7xl lg:text-8xl font-bold uppercase leading-[0.95] tracking-tighter mb-10 text-white group cursor-pointer">
Let's<br> Let's<br>
<span class="text-stroke group-hover:text-brand-accent transition-all duration-500 ease-out">Build</span><br> <span class="text-stroke group-hover:text-brand-accent transition-all duration-500 ease-out">Build</span><br>
Reality. Reality.
@ -18,28 +18,28 @@ const today = new Date();
<div class="md:text-right animate-on-scroll slide-left stagger-2"> <div class="md:text-right animate-on-scroll slide-left stagger-2">
<div class="mb-14"> <div class="mb-14">
<p class="text-xs font-bold uppercase text-[var(--theme-text-muted)] mb-6 tracking-widest">Social Uplink</p> <p class="text-xs font-bold uppercase text-slate-500 mb-6 tracking-widest">Social Uplink</p>
<ul class="space-y-3"> <ul class="space-y-3">
<li> <li>
<a href="https://nicholai.work" class="text-[var(--theme-text-primary)] hover:text-brand-accent text-lg font-mono transition-colors duration-300 inline-block"> <a href="https://nicholai.work" class="text-white hover:text-brand-accent text-lg font-mono transition-colors duration-300 inline-block">
nicholai.work nicholai.work
</a> </a>
</li> </li>
<li> <li>
<a href="https://instagram.com/nicholai.exe/" class="text-[var(--theme-text-primary)] hover:text-brand-accent text-lg font-mono transition-colors duration-300 inline-block"> <a href="https://instagram.com/nicholai.exe/" class="text-white hover:text-brand-accent text-lg font-mono transition-colors duration-300 inline-block">
@nicholai.exe @nicholai.exe
</a> </a>
</li> </li>
<li> <li>
<a href="https://www.linkedin.com/in/nicholai-vogel-7a6b85112/" class="text-[var(--theme-text-primary)] hover:text-brand-accent text-lg font-mono transition-colors duration-300 inline-block"> <a href="https://www.linkedin.com/in/nicholai-vogel-7a6b85112/" class="text-white hover:text-brand-accent text-lg font-mono transition-colors duration-300 inline-block">
LinkedIn LinkedIn
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="flex md:justify-end items-end gap-3 text-[10px] text-[var(--theme-text-muted)] font-mono uppercase tracking-wide"> <div class="flex md:justify-end items-end gap-3 text-[10px] text-slate-600 font-mono uppercase tracking-wide">
<span>&copy; {today.getFullYear()} Nicholai Vogel</span> <span>&copy; {today.getFullYear()} Nicholai Vogel</span>
<span class="text-[var(--theme-text-subtle)]">/</span> <span class="text-slate-700">/</span>
<span>V7 SYSTEM</span> <span>V7 SYSTEM</span>
</div> </div>
</div> </div>
@ -47,6 +47,6 @@ const today = new Date();
<!-- Decorative huge text bg --> <!-- Decorative huge text bg -->
<div class="absolute -bottom-8 lg:-bottom-12 left-1/2 -translate-x-1/2 w-full text-center pointer-events-none select-none"> <div class="absolute -bottom-8 lg:-bottom-12 left-1/2 -translate-x-1/2 w-full text-center pointer-events-none select-none">
<span class="text-[12rem] md:text-[18rem] lg:text-[22rem] font-extrabold text-[var(--theme-text-primary)] opacity-[var(--theme-decorative-opacity)] uppercase leading-none whitespace-nowrap tracking-tighter transition-opacity duration-300">VOGEL</span> <span class="text-[12rem] md:text-[18rem] lg:text-[22rem] font-extrabold text-white/[0.02] uppercase leading-none whitespace-nowrap tracking-tighter">VOGEL</span>
</div> </div>
</footer> </footer>

View File

@ -5,16 +5,17 @@
<!-- 12 Column Guide (Visual Only - Low Opacity) --> <!-- 12 Column Guide (Visual Only - Low Opacity) -->
<div <div
class="fixed inset-0 container mx-auto px-6 lg:px-12 grid grid-cols-4 md:grid-cols-12 gap-4 pointer-events-none z-0 opacity-10 border-x border-[var(--theme-border-secondary)]"> class="fixed inset-0 container mx-auto px-6 lg:px-12 grid grid-cols-4 md:grid-cols-12 gap-4 pointer-events-none z-0 opacity-10 border-x border-white/5">
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
<div class="border-r border-[var(--theme-border-secondary)] h-full hidden md:block"></div> <div class="border-r border-white/5 h-full hidden md:block"></div>
</div> </div>

View File

@ -1,23 +1,21 @@
--- ---
import ThemeToggle from './ThemeToggle.astro'; ---
---
--- ---
<nav class="fixed top-0 left-0 w-full z-50 px-6 lg:px-12 py-6 lg:py-8 flex justify-between items-center backdrop-blur-md bg-[var(--theme-overlay)] border-b border-[var(--theme-border-secondary)]"> <nav class="fixed top-0 left-0 w-full z-50 px-6 lg:px-12 py-6 lg:py-8 flex justify-between items-center backdrop-blur-md bg-brand-dark/80 border-b border-white/5">
<!-- Left side - branding and theme toggle --> <!-- Left side - can be empty or have subtle branding -->
<div class="flex items-center gap-6">
<a href="/" class="text-[10px] font-mono text-[var(--theme-text-muted)] tracking-widest uppercase hover:text-brand-accent transition-colors duration-300">NV / 2026</a>
<div class="hidden md:block"> <div class="hidden md:block">
<ThemeToggle /> <a href="/" class="text-[10px] font-mono text-slate-600 tracking-widest uppercase hover:text-brand-accent transition-colors duration-300">NV / 2026</a>
</div>
</div> </div>
<!-- Right side navigation --> <!-- Right side navigation -->
<div class="flex items-center gap-6 lg:gap-10 ml-auto"> <div class="flex items-center gap-8 lg:gap-12 ml-auto">
<div class="hidden md:flex items-center gap-10 lg:gap-12"> <div class="hidden md:flex items-center gap-10 lg:gap-12">
<a href="/" <a href="/"
class:list={[ class:list={[
"relative text-xs font-semibold uppercase tracking-[0.15em] transition-all duration-300 py-2 group", "relative text-xs font-semibold uppercase tracking-[0.15em] transition-all duration-300 py-2 group",
Astro.url.pathname === '/' ? "text-[var(--theme-text-primary)]" : "text-[var(--theme-text-muted)] hover:text-[var(--theme-text-primary)]" Astro.url.pathname === '/' ? "text-white" : "text-slate-500 hover:text-white"
]}> ]}>
<span class="relative z-10">Home</span> <span class="relative z-10">Home</span>
<span class:list={[ <span class:list={[
@ -28,7 +26,7 @@ import ThemeToggle from './ThemeToggle.astro';
<a href="/blog" <a href="/blog"
class:list={[ class:list={[
"relative text-xs font-semibold uppercase tracking-[0.15em] transition-all duration-300 py-2 group", "relative text-xs font-semibold uppercase tracking-[0.15em] transition-all duration-300 py-2 group",
Astro.url.pathname.startsWith('/blog') ? "text-[var(--theme-text-primary)]" : "text-[var(--theme-text-muted)] hover:text-[var(--theme-text-primary)]" Astro.url.pathname.startsWith('/blog') ? "text-white" : "text-slate-500 hover:text-white"
]}> ]}>
<span class="relative z-10">Blog</span> <span class="relative z-10">Blog</span>
<span class:list={[ <span class:list={[
@ -43,17 +41,16 @@ import ThemeToggle from './ThemeToggle.astro';
"hidden md:block border px-5 lg:px-6 py-2.5 lg:py-3 text-xs font-bold uppercase tracking-[0.15em] transition-all duration-300", "hidden md:block border px-5 lg:px-6 py-2.5 lg:py-3 text-xs font-bold uppercase tracking-[0.15em] transition-all duration-300",
Astro.url.pathname.startsWith('/contact') Astro.url.pathname.startsWith('/contact')
? "border-brand-accent bg-brand-accent text-brand-dark" ? "border-brand-accent bg-brand-accent text-brand-dark"
: "border-[var(--theme-border-strong)] text-[var(--theme-text-primary)] hover:border-brand-accent hover:bg-brand-accent hover:text-brand-dark" : "border-slate-600 text-white hover:border-brand-accent hover:bg-brand-accent hover:text-brand-dark"
]}> ]}>
Let's Talk Let's Talk
</a> </a>
</div> </div>
<!-- Mobile menu button --> <!-- Mobile menu button -->
<div class="md:hidden flex items-center">
<button <button
id="mobile-menu-toggle" id="mobile-menu-toggle"
class="p-2 text-[var(--theme-text-muted)] hover:text-[var(--theme-text-primary)] transition-colors z-[60]" class="md:hidden p-2 text-slate-400 hover:text-white transition-colors z-[60]"
aria-label="Toggle menu" aria-label="Toggle menu"
aria-expanded="false" aria-expanded="false"
> >
@ -66,13 +63,12 @@ import ThemeToggle from './ThemeToggle.astro';
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12"></path>
</svg> </svg>
</button> </button>
</div>
</nav> </nav>
<!-- Mobile Menu Overlay --> <!-- Mobile Menu Overlay -->
<div <div
id="mobile-menu" id="mobile-menu"
class="fixed inset-0 z-40 bg-[var(--theme-overlay-heavy)] backdrop-blur-xl transform translate-x-full transition-transform duration-300 ease-out md:hidden" class="fixed inset-0 z-40 bg-brand-dark/98 backdrop-blur-xl transform translate-x-full transition-transform duration-300 ease-out md:hidden"
> >
<!-- Menu Content --> <!-- Menu Content -->
<div class="flex flex-col justify-center items-center h-full px-8"> <div class="flex flex-col justify-center items-center h-full px-8">
@ -80,19 +76,19 @@ import ThemeToggle from './ThemeToggle.astro';
<nav class="flex flex-col items-center gap-8 mb-12"> <nav class="flex flex-col items-center gap-8 mb-12">
<a <a
href="/" href="/"
class="mobile-nav-link text-3xl font-bold uppercase tracking-wider text-[var(--theme-text-primary)] hover:text-brand-accent transition-colors duration-300" class="mobile-nav-link text-3xl font-bold uppercase tracking-wider text-white hover:text-brand-accent transition-colors duration-300"
> >
Home Home
</a> </a>
<a <a
href="/blog" href="/blog"
class="mobile-nav-link text-3xl font-bold uppercase tracking-wider text-[var(--theme-text-primary)] hover:text-brand-accent transition-colors duration-300" class="mobile-nav-link text-3xl font-bold uppercase tracking-wider text-white hover:text-brand-accent transition-colors duration-300"
> >
Blog Blog
</a> </a>
<a <a
href="/contact" href="/contact"
class="mobile-nav-link text-3xl font-bold uppercase tracking-wider text-[var(--theme-text-primary)] hover:text-brand-accent transition-colors duration-300" class="mobile-nav-link text-3xl font-bold uppercase tracking-wider text-white hover:text-brand-accent transition-colors duration-300"
> >
Contact Contact
</a> </a>
@ -101,21 +97,16 @@ import ThemeToggle from './ThemeToggle.astro';
<!-- CTA Button --> <!-- CTA Button -->
<a <a
href="/contact" href="/contact"
class="border border-brand-accent px-8 py-4 text-sm font-bold uppercase tracking-[0.2em] text-brand-accent hover:bg-brand-accent hover:text-brand-dark transition-all duration-300 mb-8" class="border border-brand-accent px-8 py-4 text-sm font-bold uppercase tracking-[0.2em] text-brand-accent hover:bg-brand-accent hover:text-brand-dark transition-all duration-300"
> >
Let's Talk Let's Talk
</a> </a>
<!-- Decorative Elements --> <!-- Decorative Elements -->
<div class="absolute bottom-12 left-8 right-8 flex justify-between items-center"> <div class="absolute bottom-12 left-8 right-8">
<div class="flex flex-col gap-2"> <div class="flex justify-between items-center text-[10px] font-mono text-slate-600 uppercase tracking-widest">
<div class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest"> <span>NV / 2026</span>
NV / 2026 <span>Menu</span>
</div>
<ThemeToggle />
</div>
<div class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest self-end">
Menu
</div> </div>
</div> </div>
</div> </div>

View File

@ -17,12 +17,12 @@ const { prevPost, nextPost } = Astro.props;
--- ---
{(prevPost || nextPost) && ( {(prevPost || nextPost) && (
<nav class="post-navigation mt-20 pt-12 border-t border-[var(--theme-border-primary)]" aria-label="Post navigation"> <nav class="post-navigation mt-20 pt-12 border-t border-white/10" aria-label="Post navigation">
<div class="flex items-center gap-4 mb-8"> <div class="flex items-center gap-4 mb-8">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest font-bold"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest font-bold">
/// NEXT_IN_SEQUENCE /// NEXT_IN_SEQUENCE
</span> </span>
<span class="h-px flex-grow bg-[var(--theme-border-primary)]"></span> <span class="h-px flex-grow bg-white/10"></span>
</div> </div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
@ -30,24 +30,24 @@ const { prevPost, nextPost } = Astro.props;
{prevPost ? ( {prevPost ? (
<a <a
href={prevPost.href} href={prevPost.href}
class="group relative flex items-center gap-6 p-6 border border-[var(--theme-border-primary)] bg-[var(--theme-hover-bg)] hover:border-brand-accent/40 hover:bg-[var(--theme-hover-bg-strong)] transition-all duration-500 overflow-hidden" class="group relative flex items-center gap-6 p-6 border border-white/10 bg-white/[0.02] hover:border-brand-accent/40 hover:bg-white/[0.04] transition-all duration-500 overflow-hidden"
> >
<div class="absolute top-0 left-0 w-[2px] h-full bg-[var(--theme-text-subtle)] opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div> <div class="absolute top-0 left-0 w-[2px] h-full bg-slate-700 opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div>
<div class="absolute inset-0 bg-brand-accent/5 translate-x-[-100%] group-hover:translate-x-0 transition-transform duration-500 pointer-events-none"></div> <div class="absolute inset-0 bg-brand-accent/5 translate-x-[-100%] group-hover:translate-x-0 transition-transform duration-500 pointer-events-none"></div>
<!-- Content --> <!-- Content -->
<div class="flex-grow min-w-0 z-10"> <div class="flex-grow min-w-0 z-10">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest mb-2 block group-hover:text-brand-accent transition-colors"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest mb-2 block group-hover:text-brand-accent transition-colors">
&lt; PREV_FILE &lt; PREV_FILE
</span> </span>
<h4 class="text-sm font-bold text-[var(--theme-text-primary)] uppercase tracking-tight truncate group-hover:text-brand-accent transition-colors"> <h4 class="text-sm font-bold text-white uppercase tracking-tight truncate group-hover:text-brand-accent transition-colors">
{prevPost.title} {prevPost.title}
</h4> </h4>
</div> </div>
<!-- Thumbnail --> <!-- Thumbnail -->
{prevPost.heroImage && ( {prevPost.heroImage && (
<div class="hidden sm:block flex-shrink-0 w-12 h-12 overflow-hidden border border-[var(--theme-border-primary)] z-10 grayscale group-hover:grayscale-0 transition-all duration-500"> <div class="hidden sm:block flex-shrink-0 w-12 h-12 overflow-hidden border border-white/10 z-10 grayscale group-hover:grayscale-0 transition-all duration-500">
<Image <Image
src={prevPost.heroImage} src={prevPost.heroImage}
alt="" alt=""
@ -59,8 +59,8 @@ const { prevPost, nextPost } = Astro.props;
)} )}
</a> </a>
) : ( ) : (
<div class="border border-[var(--theme-border-secondary)] bg-[var(--theme-hover-bg)] p-6 flex items-center justify-center"> <div class="border border-white/5 bg-white/[0.01] p-6 flex items-center justify-center">
<span class="text-[10px] font-mono text-[var(--theme-text-subtle)] uppercase tracking-widest">/// START_OF_ARCHIVE</span> <span class="text-[10px] font-mono text-slate-600 uppercase tracking-widest">/// START_OF_ARCHIVE</span>
</div> </div>
)} )}
@ -68,14 +68,14 @@ const { prevPost, nextPost } = Astro.props;
{nextPost ? ( {nextPost ? (
<a <a
href={nextPost.href} href={nextPost.href}
class="group relative flex items-center gap-6 p-6 border border-[var(--theme-border-primary)] bg-[var(--theme-hover-bg)] hover:border-brand-accent/40 hover:bg-[var(--theme-hover-bg-strong)] transition-all duration-500 overflow-hidden" class="group relative flex items-center gap-6 p-6 border border-white/10 bg-white/[0.02] hover:border-brand-accent/40 hover:bg-white/[0.04] transition-all duration-500 overflow-hidden"
> >
<div class="absolute top-0 right-0 w-[2px] h-full bg-[var(--theme-text-subtle)] opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div> <div class="absolute top-0 right-0 w-[2px] h-full bg-slate-700 opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div>
<div class="absolute inset-0 bg-brand-accent/5 translate-x-[100%] group-hover:translate-x-0 transition-transform duration-500 pointer-events-none"></div> <div class="absolute inset-0 bg-brand-accent/5 translate-x-[100%] group-hover:translate-x-0 transition-transform duration-500 pointer-events-none"></div>
<!-- Thumbnail --> <!-- Thumbnail -->
{nextPost.heroImage && ( {nextPost.heroImage && (
<div class="hidden sm:block flex-shrink-0 w-12 h-12 overflow-hidden border border-[var(--theme-border-primary)] z-10 grayscale group-hover:grayscale-0 transition-all duration-500"> <div class="hidden sm:block flex-shrink-0 w-12 h-12 overflow-hidden border border-white/10 z-10 grayscale group-hover:grayscale-0 transition-all duration-500">
<Image <Image
src={nextPost.heroImage} src={nextPost.heroImage}
alt="" alt=""
@ -88,19 +88,20 @@ const { prevPost, nextPost } = Astro.props;
<!-- Content --> <!-- Content -->
<div class="flex-grow min-w-0 text-right z-10"> <div class="flex-grow min-w-0 text-right z-10">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest mb-2 block group-hover:text-brand-accent transition-colors"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest mb-2 block group-hover:text-brand-accent transition-colors">
NEXT_FILE &gt; NEXT_FILE &gt;
</span> </span>
<h4 class="text-sm font-bold text-[var(--theme-text-primary)] uppercase tracking-tight truncate group-hover:text-brand-accent transition-colors"> <h4 class="text-sm font-bold text-white uppercase tracking-tight truncate group-hover:text-brand-accent transition-colors">
{nextPost.title} {nextPost.title}
</h4> </h4>
</div> </div>
</a> </a>
) : ( ) : (
<div class="border border-[var(--theme-border-secondary)] bg-[var(--theme-hover-bg)] p-6 flex items-center justify-center"> <div class="border border-white/5 bg-white/[0.01] p-6 flex items-center justify-center">
<span class="text-[10px] font-mono text-[var(--theme-text-subtle)] uppercase tracking-widest">/// END_OF_ARCHIVE</span> <span class="text-[10px] font-mono text-slate-600 uppercase tracking-widest">/// END_OF_ARCHIVE</span>
</div> </div>
)} )}
</div> </div>
</nav> </nav>
)} )}

View File

@ -2,13 +2,13 @@
// Reading progress bar that tracks scroll position // Reading progress bar that tracks scroll position
--- ---
<div id="reading-progress-container" class="fixed top-0 left-0 w-full h-[3px] z-[100] bg-[var(--theme-bg-primary)]/50"> <div id="reading-progress-container" class="fixed top-0 left-0 w-full h-[3px] z-[100] bg-brand-dark/50">
<div id="reading-progress-bar" class="h-full bg-brand-accent w-0 transition-[width] duration-100 ease-out shadow-[0_0_10px_rgba(221,65,50,0.5)]"></div> <div id="reading-progress-bar" class="h-full bg-brand-accent w-0 transition-[width] duration-100 ease-out shadow-[0_0_10px_rgba(221,65,50,0.5)]"></div>
</div> </div>
<div id="reading-status" class="fixed top-4 right-4 z-[90] hidden lg:flex items-center gap-3 px-3 py-1 bg-[var(--theme-overlay)] backdrop-blur-md border border-[var(--theme-border-primary)] opacity-0 transition-opacity duration-300 pointer-events-none"> <div id="reading-status" class="fixed top-4 right-4 z-[90] hidden lg:flex items-center gap-3 px-3 py-1 bg-brand-dark/80 backdrop-blur-md border border-white/10 opacity-0 transition-opacity duration-300 pointer-events-none">
<div class="w-1.5 h-1.5 bg-brand-accent rounded-full animate-pulse"></div> <div class="w-1.5 h-1.5 bg-brand-accent rounded-full animate-pulse"></div>
<span class="text-[9px] font-mono text-[var(--theme-text-secondary)] uppercase tracking-widest">READING_BUFFER: <span id="progress-text" class="text-[var(--theme-text-primary)]">0%</span></span> <span class="text-[9px] font-mono text-slate-400 uppercase tracking-widest">READING_BUFFER: <span id="progress-text" class="text-white">0%</span></span>
</div> </div>
<script> <script>
@ -69,3 +69,4 @@
// Re-initialize on Astro page transitions // Re-initialize on Astro page transitions
document.addEventListener('astro:page-load', initReadingProgress); document.addEventListener('astro:page-load', initReadingProgress);
</script> </script>

View File

@ -21,12 +21,12 @@ const { posts, class: className = '' } = Astro.props;
--- ---
{posts.length > 0 && ( {posts.length > 0 && (
<section class:list={['related-posts mt-20 pt-12 border-t border-[var(--theme-border-primary)]', className]}> <section class:list={['related-posts mt-20 pt-12 border-t border-white/10', className]}>
<div class="flex items-center gap-4 mb-8"> <div class="flex items-center gap-4 mb-8">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest font-bold"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest font-bold">
/// RELATED_ARCHIVES /// RELATED_ARCHIVES
</span> </span>
<span class="h-px flex-grow bg-[var(--theme-border-primary)]"></span> <span class="h-px flex-grow bg-white/10"></span>
</div> </div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@ -45,3 +45,4 @@ const { posts, class: className = '' } = Astro.props;
</div> </div>
</section> </section>
)} )}

View File

@ -17,10 +17,10 @@ const tocHeadings = headings.filter((h) => h.depth === 2 || h.depth === 3);
{tocHeadings.length > 0 && ( {tocHeadings.length > 0 && (
<nav class:list={['toc', className]} data-toc aria-label="Table of contents"> <nav class:list={['toc', className]} data-toc aria-label="Table of contents">
<div class="flex items-center gap-3 mb-6"> <div class="flex items-center gap-3 mb-6">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest font-bold"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest font-bold">
/// CONTENTS /// CONTENTS
</span> </span>
<span class="h-px flex-grow bg-[var(--theme-border-primary)]"></span> <span class="h-px flex-grow bg-white/10"></span>
</div> </div>
<ul class="space-y-3"> <ul class="space-y-3">
{tocHeadings.map((heading) => ( {tocHeadings.map((heading) => (
@ -29,15 +29,15 @@ const tocHeadings = headings.filter((h) => h.depth === 2 || h.depth === 3);
href={`#${heading.slug}`} href={`#${heading.slug}`}
data-toc-link={heading.slug} data-toc-link={heading.slug}
class:list={[ class:list={[
'toc-link block text-sm transition-all duration-300 hover:text-[var(--theme-text-primary)]', 'toc-link block text-sm transition-all duration-300 hover:text-white',
heading.depth === 2 heading.depth === 2
? 'text-[var(--theme-text-secondary)] font-medium' ? 'text-slate-400 font-medium'
: 'text-[var(--theme-text-muted)] pl-4 text-xs', : 'text-slate-500 pl-4 text-xs',
]} ]}
> >
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
{heading.depth === 2 && ( {heading.depth === 2 && (
<span class="w-1.5 h-1.5 bg-[var(--theme-text-subtle)] toc-indicator transition-colors duration-300"></span> <span class="w-1.5 h-1.5 bg-slate-600 toc-indicator transition-colors duration-300"></span>
)} )}
{heading.text} {heading.text}
</span> </span>
@ -78,23 +78,23 @@ const tocHeadings = headings.filter((h) => h.depth === 2 || h.depth === 3);
if (activeHeading && currentActive !== activeHeading) { if (activeHeading && currentActive !== activeHeading) {
// Remove active state from all links // Remove active state from all links
tocLinks.forEach((link) => { tocLinks.forEach((link) => {
link.classList.remove('text-brand-accent', 'text-[var(--theme-text-primary)]'); link.classList.remove('text-brand-accent', 'text-white');
link.classList.add('text-[var(--theme-text-secondary)]'); link.classList.add('text-slate-400');
const indicator = link.querySelector('.toc-indicator'); const indicator = link.querySelector('.toc-indicator');
if (indicator) { if (indicator) {
indicator.classList.remove('bg-brand-accent'); indicator.classList.remove('bg-brand-accent');
indicator.classList.add('bg-[var(--theme-text-subtle)]'); indicator.classList.add('bg-slate-600');
} }
}); });
// Add active state to current link // Add active state to current link
const activeLink = document.querySelector(`[data-toc-link="${activeHeading.id}"]`); const activeLink = document.querySelector(`[data-toc-link="${activeHeading.id}"]`);
if (activeLink) { if (activeLink) {
activeLink.classList.remove('text-[var(--theme-text-secondary)]'); activeLink.classList.remove('text-slate-400');
activeLink.classList.add('text-brand-accent'); activeLink.classList.add('text-brand-accent');
const indicator = activeLink.querySelector('.toc-indicator'); const indicator = activeLink.querySelector('.toc-indicator');
if (indicator) { if (indicator) {
indicator.classList.remove('bg-[var(--theme-text-subtle)]'); indicator.classList.remove('bg-slate-600');
indicator.classList.add('bg-brand-accent'); indicator.classList.add('bg-brand-accent');
} }
} }

View File

@ -1,87 +0,0 @@
---
---
<div class="theme-toggle-group flex items-center gap-3 ml-2 select-none" role="group" aria-label="Theme selector">
<div class="flex items-center text-[var(--theme-text-subtle)] opacity-50">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<polyline points="15 10 20 15 15 20"></polyline>
<path d="M4 4v7a4 4 0 0 0 4 4h12"></path>
</svg>
</div>
<div class="flex items-center gap-2.5">
<button
type="button"
class="theme-toggle-dark w-2.5 h-2.5 rounded-full bg-[#000] border border-white/20 hover:border-brand-accent/50 transition-all duration-300 relative group cursor-pointer"
aria-label="Dark theme"
title="Dark theme"
>
<span class="absolute -inset-1 border border-brand-accent rounded-full opacity-0 group-[.is-current-theme]:opacity-100 transition-opacity duration-300"></span>
</button>
<button
type="button"
class="theme-toggle-light w-2.5 h-2.5 rounded-full bg-[#efefef] border border-black/10 hover:border-brand-accent/50 transition-all duration-300 relative group cursor-pointer"
aria-label="Light theme"
title="Light theme"
>
<span class="absolute -inset-1 border border-brand-accent rounded-full opacity-0 group-[.is-current-theme]:opacity-100 transition-opacity duration-300"></span>
</button>
</div>
</div>
<script>
function initThemeToggle() {
const groups = document.querySelectorAll('.theme-toggle-group');
function getTheme(): 'dark' | 'light' {
const stored = localStorage.getItem('theme');
if (stored === 'light' || stored === 'dark') {
return stored;
}
return 'dark';
}
function updateAllToggles(theme: 'dark' | 'light') {
groups.forEach(group => {
const darkBtn = group.querySelector('.theme-toggle-dark');
const lightBtn = group.querySelector('.theme-toggle-light');
darkBtn?.classList.remove('is-current-theme');
lightBtn?.classList.remove('is-current-theme');
if (theme === 'dark') {
darkBtn?.classList.add('is-current-theme');
} else {
lightBtn?.classList.add('is-current-theme');
}
});
}
function setTheme(theme: 'dark' | 'light') {
if (document.documentElement.getAttribute('data-theme') === theme) return;
document.documentElement.classList.add('theme-transition');
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
updateAllToggles(theme);
setTimeout(() => {
document.documentElement.classList.remove('theme-transition');
}, 300);
}
const currentTheme = getTheme();
updateAllToggles(currentTheme);
groups.forEach(group => {
const darkBtn = group.querySelector('.theme-toggle-dark');
const lightBtn = group.querySelector('.theme-toggle-light');
darkBtn?.addEventListener('click', () => setTheme('dark'));
lightBtn?.addEventListener('click', () => setTheme('light'));
});
}
initThemeToggle();
document.addEventListener('astro:page-load', initThemeToggle);
</script>

View File

@ -25,126 +25,87 @@ interface Props {
const { sectionTitle, sectionSubtitle, sectionLabel, description, entries } = Astro.props; const { sectionTitle, sectionSubtitle, sectionLabel, description, entries } = Astro.props;
--- ---
<section id="experience" class="w-full py-32 border-t border-[var(--theme-border-primary)] bg-[var(--theme-bg-primary)] overflow-hidden"> <section id="experience" class="container mx-auto px-6 lg:px-12 py-32 border-t border-white/10">
<div class="container mx-auto px-6 lg:px-12">
<!-- Section Header --> <!-- Section Header -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-24 lg:mb-32"> <div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-24 lg:mb-32 group cursor-pointer">
<div class="lg:col-span-8 group cursor-default"> <div class="lg:col-span-8">
<div class="flex items-center gap-3 mb-6 intro-element animate-on-scroll fade-in"> <h2 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white">
<div class="w-2 h-2 bg-brand-accent animate-pulse"></div> <span class="block animate-on-scroll slide-up">{sectionTitle}</span>
<span class="font-mono text-[10px] uppercase tracking-[0.3em] text-brand-accent">SYS.RECORDS /// WORK_HISTORY</span> <span class="block animate-on-scroll slide-up stagger-1 text-stroke group-hover:text-brand-accent transition-all duration-500 ease-out">{sectionSubtitle}</span>
</div>
<h2 class="text-5xl md:text-7xl lg:text-8xl font-bold uppercase tracking-tighter leading-[0.85] text-[var(--theme-text-primary)]">
<span class="block">{sectionTitle}</span>
<span class="block text-brand-accent">
{sectionSubtitle}
</span>
</h2> </h2>
</div> </div>
<div class="lg:col-span-4 flex flex-col justify-end"> <div class="lg:col-span-4 flex items-end">
<div class="font-mono text-[10px] text-[var(--theme-text-subtle)] uppercase tracking-widest mb-4 animate-on-scroll fade-in stagger-2 flex items-center gap-2"> <p class="text-slate-400 text-lg leading-relaxed animate-on-scroll slide-up stagger-2 border-l-2 border-brand-accent pl-6">
<span class="w-8 h-px bg-brand-accent/30"></span>
DATA_ARCHIVE_V7
</div>
<p class="text-[var(--theme-text-secondary)] text-lg leading-relaxed animate-on-scroll slide-up stagger-2 border-l border-brand-accent/30 pl-6">
{description} {description}
</p> </p>
</div> </div>
</div> </div>
<!-- Experience List --> <!-- Experience List -->
<div class="w-full border-t border-[var(--theme-border-primary)]"> <div class="w-full border-t border-white/10">
{entries.map((entry, index) => ( {entries.map((entry, index) => (
<div class="group relative border-b border-[var(--theme-border-primary)] hover:bg-white/[0.01] transition-all duration-500 overflow-hidden">
<!-- Industrial Side Accent -->
<div class="absolute left-0 top-0 bottom-0 w-1 bg-brand-accent transform -translate-x-full group-hover:translate-x-0 transition-transform duration-500 ease-out"></div>
<a <a
href={entry.link?.url || '#'} href={entry.link?.url || '#'}
class="block py-12 lg:py-16 px-4 lg:px-8" class="group block border-b border-white/10 py-10 hover:border-brand-accent/30 transition-colors duration-300"
> >
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start"> <!-- Entry Header -->
<!-- Left: Header & Role --> <div class="flex items-baseline justify-between mb-6">
<div class="lg:col-span-4"> <div class="flex-grow">
<div class="flex items-center gap-4 mb-4"> <h3 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">
<span class="font-mono text-xs text-brand-accent opacity-50 group-hover:opacity-100 transition-opacity">[{entry.systemId || `EXP.0${index + 1}`}]</span>
<div class="flex items-center gap-2">
<div class={`w-1.5 h-1.5 rounded-full ${index === 0 ? 'bg-brand-accent animate-pulse' : 'bg-[var(--theme-text-subtle)]'}`}></div>
<span class="font-mono text-[9px] uppercase tracking-widest text-[var(--theme-text-muted)]">{index === 0 ? 'PRODUCTION_LIVE' : 'PRODUCTION_WRAP'}</span>
</div>
</div>
<h3 class="text-4xl md:text-5xl lg:text-6xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300 mb-4">
{entry.company} {entry.company}
</h3> </h3>
<p class="font-mono text-xs uppercase tracking-[0.2em] text-[var(--theme-text-secondary)]"> <p class="text-sm font-mono text-slate-400 mt-2">
{entry.role} {entry.role}
</p> </p>
</div> </div>
<div class="hidden md:block text-right ml-12 flex-shrink-0">
<!-- Middle: Metadata --> <div class="text-sm font-mono text-brand-accent">{String(index + 1).padStart(2, '0')}</div>
<div class="lg:col-span-3 space-y-8 pt-2">
<div>
<div class="text-[10px] font-mono uppercase tracking-[0.2em] text-[var(--theme-text-muted)] mb-3 flex items-center gap-2">
<span class="text-brand-accent">/</span> DUR.TIMELINE
</div> </div>
<div class="font-mono text-sm text-[var(--theme-text-primary)]">{entry.dates}</div> </div>
<!-- Entry Content Grid -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-12">
<!-- Left Column: Metadata -->
<div class="lg:col-span-4 space-y-6">
<div>
<div class="text-[10px] font-mono uppercase tracking-widest text-slate-500 mb-2">Period</div>
<div class="font-bold text-white">{entry.dates}</div>
</div> </div>
{entry.tags && entry.tags.length > 0 && ( {entry.tags && entry.tags.length > 0 && (
<div> <div>
<div class="text-[10px] font-mono uppercase tracking-[0.2em] text-[var(--theme-text-muted)] mb-3 flex items-center gap-2"> <div class="text-[10px] font-mono uppercase tracking-widest text-slate-500 mb-2">Stack</div>
<span class="text-brand-accent">/</span> PIP.TOOLSET <div class="text-slate-400 font-mono text-xs md:text-sm tracking-wide group-hover:text-white transition-colors duration-300">
</div> {entry.tags.join(', ')}
<div class="flex flex-wrap gap-2">
{entry.tags.map(tag => (
<span class="text-[9px] font-mono uppercase tracking-wider px-2 py-1 border border-[var(--theme-border-secondary)] text-[var(--theme-text-muted)] group-hover:border-brand-accent/30 group-hover:text-[var(--theme-text-secondary)] transition-all">
{tag}
</span>
))}
</div> </div>
</div> </div>
)} )}
</div> </div>
<!-- Right: Content --> <!-- Right Column: Description -->
<div class="lg:col-span-5 pt-2"> <div class="lg:col-span-8">
<div class="text-[10px] font-mono uppercase tracking-[0.2em] text-[var(--theme-text-muted)] mb-4 flex items-center gap-2"> <p class="text-slate-400 leading-relaxed mb-6 group-hover:text-white transition-colors duration-300">
<span class="text-brand-accent">/</span> LOG.PRODUCTION_MANIFEST
</div>
<p class="text-[var(--theme-text-secondary)] leading-relaxed mb-8 group-hover:text-[var(--theme-text-primary)] transition-colors duration-300">
{entry.description} {entry.description}
</p> </p>
{entry.achievements && entry.achievements.length > 0 && ( {entry.achievements && entry.achievements.length > 0 && (
<div class="space-y-6"> <div class="space-y-4">
{entry.achievements.map((achievement) => ( {entry.achievements.map((achievement) => (
<div class="relative pl-6 py-1 group/item"> <div class="border-l-2 border-white/10 pl-4">
<!-- Minimalist bullet --> <div class="text-[10px] font-mono uppercase tracking-widest text-slate-500 mb-1">
<div class="absolute left-0 top-3 w-3 h-px bg-brand-accent/40 group-hover/item:w-5 transition-all"></div>
<div class="text-[9px] font-mono uppercase tracking-widest text-brand-accent/60 mb-1">
{achievement.label} {achievement.label}
</div> </div>
<div class="text-sm text-[var(--theme-text-secondary)] group-hover:text-[var(--theme-text-primary)] transition-colors"> <div class="text-sm text-slate-400 group-hover:text-white transition-colors duration-300">
{achievement.text} {achievement.text}
</div> </div>
</div> </div>
))} ))}
</div> </div>
)} )}
{entry.link && (
<div class="mt-8 flex items-center gap-2 font-mono text-[10px] text-brand-accent uppercase tracking-widest opacity-0 group-hover:opacity-100 translate-x-[-10px] group-hover:translate-x-0 transition-all duration-500">
<span>View Project</span>
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="square" stroke-linejoin="miter">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
</div>
)}
</div> </div>
</div> </div>
</a> </a>
</div>
))} ))}
</div> </div>
</div>
</section> </section>

View File

@ -33,33 +33,33 @@ const { role, client, year, region, projectTitle, projectSubtitle, projectDescri
<source src={videoUrl} type="video/mp4" /> <source src={videoUrl} type="video/mp4" />
</video> </video>
<!-- Cinematic Letterboxing / Gradient Vignette --> <!-- Cinematic Letterboxing / Gradient Vignette -->
<div class="absolute inset-0 bg-gradient-to-b from-[var(--theme-hero-gradient-top)] via-transparent to-[var(--theme-hero-gradient-top)] pointer-events-none transition-colors duration-500"></div> <div class="absolute inset-0 bg-gradient-to-b from-brand-dark/80 via-transparent to-brand-dark/80 pointer-events-none"></div>
<div class="absolute inset-0 bg-gradient-to-r from-[var(--theme-hero-gradient-side)] via-transparent to-[var(--theme-hero-gradient-side)] pointer-events-none transition-colors duration-500"></div> <div class="absolute inset-0 bg-gradient-to-r from-brand-dark/40 via-transparent to-brand-dark/40 pointer-events-none"></div>
<!-- Subtle Grid Overlay --> <!-- Subtle Grid Overlay -->
<div class="absolute inset-0 bg-[linear-gradient(var(--theme-grid-line)_1px,transparent_1px),linear-gradient(90deg,var(--theme-grid-line)_1px,transparent_1px)] bg-[size:60px_60px] pointer-events-none opacity-30"></div> <div class="absolute inset-0 bg-[linear-gradient(rgba(255,255,255,0.02)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.02)_1px,transparent_1px)] bg-[size:60px_60px] pointer-events-none opacity-30"></div>
</div> </div>
<!-- Main Content Container - Spaced to frame the video --> <!-- Main Content Container - Spaced to frame the video -->
<div class="container mx-auto px-6 lg:px-12 relative z-10 flex-1 flex flex-col justify-between py-12 lg:py-16 pointer-events-none"> <div class="container mx-auto px-6 lg:px-12 relative z-10 flex-1 flex flex-col justify-between py-12 lg:py-16 pointer-events-none">
<!-- TOP HUD: Telemetry Data --> <!-- TOP HUD: Telemetry Data -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 border-t border-[var(--theme-border-strong)] pt-6 animate-on-scroll slide-up"> <div class="grid grid-cols-2 md:grid-cols-4 gap-8 border-t border-white/20 pt-6 animate-on-scroll slide-up">
<div> <div>
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Role</span> <span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Role</span>
<span class="text-xl md:text-2xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tight">{role}</span> <span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">{role}</span>
</div> </div>
<div> <div>
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Client</span> <span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Client</span>
<span class="text-xl md:text-2xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tight">{client}</span> <span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">{client}</span>
</div> </div>
<div> <div>
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Year</span> <span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Year</span>
<span class="text-xl md:text-2xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tight">{year}</span> <span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">{year}</span>
</div> </div>
<div class="text-right md:text-left"> <div class="text-right md:text-left">
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Region</span> <span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Region</span>
<span class="text-xl md:text-2xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tight">{region}</span> <span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">{region}</span>
</div> </div>
</div> </div>
@ -74,15 +74,15 @@ const { role, client, year, region, projectTitle, projectSubtitle, projectDescri
</div> </div>
<!-- BOTTOM HUD: Project Details & Stats --> <!-- BOTTOM HUD: Project Details & Stats -->
<div class="border-b border-[var(--theme-border-strong)] pb-6 animate-on-scroll slide-up stagger-1"> <div class="border-b border-white/20 pb-6 animate-on-scroll slide-up stagger-1">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 items-end"> <div class="grid grid-cols-1 lg:grid-cols-12 gap-8 items-end">
<!-- Title & Description --> <!-- Title & Description -->
<div class="lg:col-span-7"> <div class="lg:col-span-7">
<h2 class="text-5xl md:text-7xl font-bold uppercase text-[var(--theme-text-primary)] mb-4 tracking-tighter leading-none"> <h2 class="text-5xl md:text-7xl font-bold uppercase text-white mb-4 tracking-tighter leading-none">
{projectTitle} <span class="text-transparent text-stroke">{projectSubtitle}</span> {projectTitle} <span class="text-transparent text-stroke">{projectSubtitle}</span>
</h2> </h2>
<p class="text-[var(--theme-text-secondary)] font-light max-w-lg text-sm md:text-base leading-relaxed"> <p class="text-slate-300 font-light max-w-lg text-sm md:text-base leading-relaxed">
{projectDescription} {projectDescription}
</p> </p>
</div> </div>
@ -92,8 +92,8 @@ const { role, client, year, region, projectTitle, projectSubtitle, projectDescri
<div class="grid grid-cols-2 gap-x-8 gap-y-4 font-mono text-xs"> <div class="grid grid-cols-2 gap-x-8 gap-y-4 font-mono text-xs">
{stats.map((stat) => ( {stats.map((stat) => (
<div class="border-l border-brand-accent/30 pl-3"> <div class="border-l border-brand-accent/30 pl-3">
<span class="block text-[var(--theme-text-muted)] text-[10px] uppercase mb-1">{stat.label}</span> <span class="block text-slate-500 text-[10px] uppercase mb-1">{stat.label}</span>
<span class="block text-[var(--theme-text-primary)] font-bold">{stat.value}</span> <span class="block text-white font-bold">{stat.value}</span>
</div> </div>
))} ))}
</div> </div>

View File

@ -13,10 +13,7 @@ interface Props {
const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bio } = Astro.props; const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bio } = Astro.props;
--- ---
<section id="hero" class="relative w-full h-[100dvh] overflow-hidden bg-[var(--theme-bg-primary)]"> <section id="hero" class="relative w-full h-[100dvh] overflow-hidden bg-brand-dark">
<!-- Industrial Scanlines -->
<div class="absolute inset-0 z-1 pointer-events-none opacity-[0.03] bg-[linear-gradient(rgba(18,16,16,0)_50%,rgba(0,0,0,0.25)_50%),linear-gradient(90deg,rgba(255,0,0,0.06),rgba(0,255,0,0.02),rgba(0,0,112,0.06))] bg-[length:100%_2px,3px_100%]"></div>
<!-- Background Image (Portrait) - Optimized with AVIF/WebP --> <!-- Background Image (Portrait) - Optimized with AVIF/WebP -->
<div class="absolute top-0 right-0 w-full md:w-1/2 h-full z-0"> <div class="absolute top-0 right-0 w-full md:w-1/2 h-full z-0">
<div class="relative w-full h-full"> <div class="relative w-full h-full">
@ -26,30 +23,20 @@ const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bi
widths={[640, 1024, 1600]} widths={[640, 1024, 1600]}
sizes="(max-width: 768px) 100vw, 50vw" sizes="(max-width: 768px) 100vw, 50vw"
alt="Nicholai Vogel portrait" alt="Nicholai Vogel portrait"
class="w-full h-full object-cover object-center opacity-0 mix-blend-luminosity transition-opacity duration-[2500ms] ease-out delay-700 intro-element" class="w-full h-full object-cover object-center opacity-0 mix-blend-luminosity md:opacity-0 transition-opacity duration-[2000ms] ease-out delay-500 intro-element"
id="hero-portrait" id="hero-portrait"
loading="eager" loading="eager"
decoding="sync" decoding="sync"
/> />
<div class="absolute inset-0 bg-gradient-to-l from-transparent via-[var(--theme-hero-gradient-side)] to-[var(--theme-bg-primary)] transition-colors duration-500"></div> <div class="absolute inset-0 bg-gradient-to-l from-transparent via-brand-dark/50 to-brand-dark"></div>
<div class="absolute inset-0 bg-gradient-to-t from-[var(--theme-bg-primary)] via-transparent to-transparent transition-colors duration-500"></div> <div class="absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent"></div>
<!-- Technical Overlay Elements -->
<div class="absolute bottom-12 right-12 hidden lg:flex flex-col items-end gap-1 font-mono text-[9px] text-brand-accent/40 uppercase tracking-[0.3em] intro-element opacity-0 delay-1000">
<span>COORD: 38.8339° N, 104.8214° W</span>
<span>ELV: 1,839M</span>
<div class="flex gap-2 mt-2">
<div class="w-8 h-px bg-brand-accent/20"></div>
<div class="w-2 h-px bg-brand-accent/40"></div>
</div>
</div>
</div> </div>
</div> </div>
<!-- The 100 Squares Grid Overlay --> <!-- The 100 Squares Grid Overlay -->
<div id="grid-container" class="absolute inset-0 z-10 w-full h-full grid grid-cols-10 grid-rows-10 pointer-events-none"> <div id="grid-container" class="absolute inset-0 z-10 w-full h-full grid grid-cols-10 grid-rows-10 pointer-events-none">
{Array.from({ length: 100 }).map((_, i) => ( {Array.from({ length: 100 }).map((_, i) => (
<div class="grid-cell w-full h-full border border-[var(--theme-border-secondary)] opacity-0 transition-all duration-500 ease-out" data-index={i}></div> <div class="grid-cell w-full h-full border border-white/5 opacity-0 transition-all duration-500 ease-out" data-index={i}></div>
))} ))}
</div> </div>
@ -59,55 +46,38 @@ const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bi
<!-- Top Metadata --> <!-- Top Metadata -->
<div class="flex justify-between items-start w-full intro-element opacity-0 translate-y-4 transition-all duration-1000 ease-out delay-300"> <div class="flex justify-between items-start w-full intro-element opacity-0 translate-y-4 transition-all duration-1000 ease-out delay-300">
<div class="flex items-center gap-3"> <div class="font-mono text-xs uppercase tracking-widest text-slate-500">
<div class="w-1.5 h-1.5 bg-brand-accent animate-pulse"></div> {portfolioYear}
<div class="font-mono text-[10px] uppercase tracking-[0.2em] text-[var(--theme-text-muted)]">
<span class="text-brand-accent mr-1">SYS.PRTF</span> / {portfolioYear}
</div> </div>
</div> <div class="font-mono text-xs text-slate-500 text-right tracking-wide">
<span class="block text-slate-600 mb-1 uppercase tracking-widest">{locationLabel}</span>
<div class="font-mono text-[10px] text-[var(--theme-text-muted)] text-right tracking-[0.15em] uppercase"> {location}<br>
<div class="mb-1 flex items-center justify-end gap-2"> <span id="clock" class="text-brand-accent">00:00:00 MST</span>
<span class="text-[var(--theme-text-subtle)]">{locationLabel}</span>
<span class="text-brand-accent font-bold">///</span>
</div>
<div class="text-[var(--theme-text-secondary)]">{location}</div>
<div id="clock" class="text-brand-accent mt-0.5">00:00:00 MST</div>
</div> </div>
</div> </div>
<!-- Main Heading & Description --> <!-- Main Heading & Description -->
<div class="max-w-5xl"> <div class="max-w-5xl">
<h1 class="text-6xl md:text-8xl lg:text-9xl tracking-tighter leading-[0.85] font-bold text-[var(--theme-text-primary)] mb-8 perspective-text"> <h1 class="text-6xl md:text-8xl lg:text-9xl tracking-tighter leading-[0.9] font-bold text-white mix-blend-overlay opacity-90 mb-8 perspective-text">
<span class="block intro-element opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-100">{headlineLine1}</span> <span class="block intro-element opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-100">{headlineLine1}</span>
<span class="block text-brand-accent opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-200 intro-element">{headlineLine2}</span> <span class="block text-brand-accent opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-200 intro-element">{headlineLine2}</span>
</h1> </h1>
<p class="font-mono text-sm md:text-base max-w-lg text-[var(--theme-text-secondary)] font-light leading-relaxed intro-element opacity-0 translate-y-6 transition-all duration-1000 ease-out delay-500"> <p class="font-mono text-sm md:text-base max-w-lg text-slate-400 font-light leading-relaxed intro-element opacity-0 translate-y-6 transition-all duration-1000 ease-out delay-500">
{bio} {bio}
</p> </p>
</div> </div>
<!-- Bottom Navigation --> <!-- Bottom Navigation -->
<div class="flex justify-between items-end w-full intro-element opacity-0 transition-all duration-1000 ease-out delay-700"> <div class="flex justify-between items-end w-full intro-element opacity-0 transition-all duration-1000 ease-out delay-700">
<a href="#experience" class="group flex items-center gap-6 py-2"> <a href="#experience" class="flex items-center justify-center w-12 h-12 border border-white/10 rounded-full text-brand-accent hover:bg-brand-accent hover:text-brand-dark transition-all duration-300 group">
<div class="relative w-12 h-12 flex items-center justify-center border border-[var(--theme-border-primary)] text-brand-accent hover:border-brand-accent hover:bg-brand-accent/5 transition-all duration-300"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="group-hover:animate-bounce">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square" stroke-linejoin="miter" class="group-hover:translate-y-1 transition-transform duration-300"> <path d="M12 5v14M19 12l-7 7-7-7"/>
<path d="M7 13l5 5 5-5M12 6v12"/>
</svg> </svg>
<!-- Technical Corner Accent -->
<div class="absolute -top-px -left-px w-2 h-2 border-t border-l border-brand-accent opacity-0 group-hover:opacity-100 transition-opacity"></div>
<div class="absolute -bottom-px -right-px w-2 h-2 border-b border-r border-brand-accent opacity-0 group-hover:opacity-100 transition-opacity"></div>
</div>
<div class="flex flex-col font-mono text-[10px] uppercase tracking-[0.2em]">
<span class="text-[var(--theme-text-muted)] group-hover:text-brand-accent transition-colors">Scroll</span>
<span class="text-[var(--theme-text-subtle)] group-hover:text-[var(--theme-text-secondary)] transition-colors">To Explore</span>
</div>
</a> </a>
<div class="hidden md:block text-right font-mono text-[10px] text-[var(--theme-text-muted)] tracking-[0.2em] uppercase"> <div class="text-right font-mono text-xs text-slate-500 tracking-widest">
<span class="text-[var(--theme-text-subtle)]">STATUS:</span> <span class="text-brand-accent">READY_FOR_INPUT</span><br> SCROLL TO EXPLORE
<span class="text-[var(--theme-text-subtle)]">INDEX:</span> 00.01 / 05.00
</div> </div>
</div> </div>
</div> </div>
@ -121,7 +91,7 @@ const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bi
} }
/* Fade out */ /* Fade out */
.grid-cell { .grid-cell {
/* Snappier fade-out */ /* Slightly faster fade-out for a snappier feel */
transition: opacity 0.6s ease-out, background-color 0.6s ease-out; transition: opacity 0.6s ease-out, background-color 0.6s ease-out;
} }

View File

@ -24,50 +24,46 @@ const imageMap: Record<string, string> = {
}; };
--- ---
<section id="skills" class="bg-[var(--theme-bg-primary)] py-32 lg:py-48 overflow-hidden relative cursor-default"> <section id="skills" class="bg-brand-dark py-32 lg:py-48 overflow-hidden relative cursor-default">
<div class="container mx-auto px-6 lg:px-12 relative z-10"> <div class="container mx-auto px-6 lg:px-12 relative z-10">
<!-- Header Section --> <!-- Header Section -->
<div class="mb-24 lg:mb-32 grid grid-cols-1 lg:grid-cols-12 gap-12"> <div class="mb-24 lg:mb-32 grid grid-cols-1 lg:grid-cols-12 gap-12">
<div class="lg:col-span-8 group cursor-default"> <div class="lg:col-span-8">
<div class="flex items-center gap-3 mb-6 intro-element animate-on-scroll fade-in"> <h2 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white">
<div class="w-2 h-2 bg-brand-accent animate-pulse"></div> <span class="block relative overflow-hidden">
<span class="font-mono text-[10px] uppercase tracking-[0.3em] text-brand-accent">SYS.TOOLSET /// PIPELINE_CAPABILITIES</span> <span class="animate-on-scroll slide-up block">{sectionTitle}</span>
</div> </span>
<h2 class="text-5xl md:text-7xl lg:text-8xl font-bold uppercase tracking-tighter leading-[0.85] text-[var(--theme-text-primary)]"> <span class="block relative overflow-hidden">
<span class="block">{sectionTitle}</span> <span class="animate-on-scroll slide-up stagger-1 block text-stroke text-transparent">{sectionSubtitle}</span>
<span class="block text-brand-accent">{sectionSubtitle}</span> </span>
</h2> </h2>
</div> </div>
<div class="lg:col-span-4 flex flex-col justify-end"> <div class="lg:col-span-4 flex items-end">
<div class="font-mono text-[10px] text-[var(--theme-text-subtle)] uppercase tracking-widest mb-4 flex items-center gap-2"> <p class="text-slate-400 text-lg leading-relaxed animate-on-scroll slide-up stagger-2 border-l-2 border-brand-accent pl-6">
<span class="w-8 h-px bg-brand-accent/30"></span>
TECH_STACK_MANIFEST
</div>
<p class="text-[var(--theme-text-secondary)] text-lg leading-relaxed border-l border-brand-accent/30 pl-6">
{description} {description}
</p> </p>
</div> </div>
</div> </div>
<!-- Skills Data Grid --> <!-- Skills Data Grid -->
<div class="w-full border-t border-[var(--theme-border-primary)]" id="skills-table"> <div class="w-full border-t border-white/10" id="skills-table">
<!-- Table Header --> <!-- Table Header -->
<div class="grid grid-cols-12 gap-4 py-8 border-b border-[var(--theme-border-primary)] text-[10px] font-mono uppercase tracking-[0.2em] text-[var(--theme-text-muted)] select-none"> <div class="grid grid-cols-12 gap-4 py-6 border-b border-white/10 text-[10px] font-mono uppercase tracking-widest text-slate-500 select-none">
<div class="col-span-2 md:col-span-1">/// ID.TAG</div> <div class="col-span-2 md:col-span-1">/// ID</div>
<div class="col-span-10 md:col-span-4">DOMAIN.SPECIALIZATION</div> <div class="col-span-10 md:col-span-4">Domain</div>
<div class="col-span-12 md:col-span-5 hidden md:block">PIP.TOOLSET</div> <div class="col-span-12 md:col-span-5 hidden md:block">Stack</div>
<div class="col-span-6 md:col-span-2 hidden md:block text-right">LVL.STATUS</div> <div class="col-span-6 md:col-span-2 hidden md:block text-right">Proficiency</div>
</div> </div>
{skills.map((skill, index) => { {skills.map((skill, index) => {
const proficiencyClass = skill.proficiency === "Expert" || skill.proficiency === "Specialist" const proficiencyClass = skill.proficiency === "Expert" || skill.proficiency === "Specialist"
? "border-brand-accent/50 text-brand-accent bg-brand-accent/5" ? "border-brand-accent/50 text-brand-accent bg-brand-accent/5"
: "border-[var(--theme-border-strong)] text-[var(--theme-text-secondary)]"; : "border-white/20 text-slate-300";
return ( return (
<div class={`skill-row group relative grid grid-cols-12 gap-4 py-10 border-b border-[var(--theme-border-primary)] items-center transition-colors duration-300 hover:border-brand-accent/30 overflow-hidden`} data-image={imageMap[skill.id] || "default"}> <div class={`skill-row group relative grid grid-cols-12 gap-4 py-10 border-b border-white/10 items-center transition-colors duration-300 hover:border-brand-accent/30 overflow-hidden ${index < skills.length - 1 ? '' : ''}`} data-image={imageMap[skill.id] || "default"}>
<!-- Hover Background Effect --> <!-- Hover Background Effect -->
<div class="absolute inset-0 bg-brand-accent/5 opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none"></div> <div class="absolute inset-0 bg-brand-accent/5 opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none"></div>
@ -79,13 +75,13 @@ const imageMap: Record<string, string> = {
<!-- Main Content (Domain) --> <!-- Main Content (Domain) -->
<div class="col-span-10 md:col-span-4 relative z-10"> <div class="col-span-10 md:col-span-4 relative z-10">
<h3 class="text-3xl md:text-5xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">{skill.domain}</h3> <h3 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">{skill.domain}</h3>
<!-- Scan line effect for ALL items on hover --> <!-- Scan line effect for ALL items on hover -->
<div class="absolute bottom-0 left-0 h-[1px] w-full bg-brand-accent transform scale-x-0 group-hover:scale-x-100 transition-transform duration-700 ease-out origin-left opacity-0 group-hover:opacity-100"></div> <div class="absolute bottom-0 left-0 h-[1px] w-full bg-brand-accent transform scale-x-0 group-hover:scale-x-100 transition-transform duration-700 ease-out origin-left opacity-0 group-hover:opacity-100"></div>
</div> </div>
<!-- Tools Stack --> <!-- Tools Stack -->
<div class="col-span-12 md:col-span-5 text-[var(--theme-text-secondary)] font-mono text-xs md:text-sm tracking-wide group-hover:text-[var(--theme-text-primary)] transition-colors duration-300 z-10"> <div class="col-span-12 md:col-span-5 text-slate-400 font-mono text-xs md:text-sm tracking-wide group-hover:text-white transition-colors duration-300 z-10">
{skill.tools} {skill.tools}
</div> </div>

View File

@ -13,5 +13,3 @@ tags: ['opinions', 'satire']
**[2025-12-18 14:32:02]** im trying to figure out what my favorite color is **[2025-12-18 14:32:02]** im trying to figure out what my favorite color is
**[2025-12-18 15:13:02]** ◈ INCIDENT REPORT #8291-Δ :: Personnel discovered singing in backwards Sumerian :: Object Class: K̵͉̈́E̴̹͝T̷͎̓E̸̳̿R̶̰̈́ :: The stars are RIGHT :: Recovered text fragment: 'ph'nglui mglw'nafh C̴t̷h̵u̷l̴h̵u̸ R'lyeh wgah'nagl fhtagn' :: Seventeen (17) observers report seeing ████ behind the moon :: Directive: OBSERVE. DO NOT ENGAGE. :: In his house at R'lyeh, dead ██████ waits dreaming :: **[2025-12-18 15:13:02]** ◈ INCIDENT REPORT #8291-Δ :: Personnel discovered singing in backwards Sumerian :: Object Class: K̵͉̈́E̴̹͝T̷͎̓E̸̳̿R̶̰̈́ :: The stars are RIGHT :: Recovered text fragment: 'ph'nglui mglw'nafh C̴t̷h̵u̷l̴h̵u̸ R'lyeh wgah'nagl fhtagn' :: Seventeen (17) observers report seeing ████ behind the moon :: Directive: OBSERVE. DO NOT ENGAGE. :: In his house at R'lyeh, dead ██████ waits dreaming ::
**[2025-12-18 18:03:12]** currently suffering because my girlfriend is going away for a sleepover with the girls and im not invited (i am a boy)

View File

@ -29,17 +29,9 @@ const {
--- ---
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" class="scroll-smooth" data-theme="dark"> <html lang="en" class="scroll-smooth">
<head> <head>
<meta name="x-nicholai-marker" content={HTML_MARKER} /> <meta name="x-nicholai-marker" content={HTML_MARKER} />
<!-- Theme initialization script - runs before page render to prevent flash -->
<script is:inline>
(function() {
const stored = localStorage.getItem('theme');
const theme = (stored === 'light' || stored === 'dark') ? stored : 'dark';
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
<BaseHead <BaseHead
title={title} title={title}
description={description} description={description}
@ -51,7 +43,7 @@ const {
<slot name="head" /> <slot name="head" />
</head> </head>
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark"> <body class="antialiased selection:bg-brand-accent selection:text-brand-dark bg-brand-dark text-white">
<!-- Only hydrate custom cursor on devices that can actually benefit from it --> <!-- Only hydrate custom cursor on devices that can actually benefit from it -->
<CustomCursor client:media="(pointer: fine) and (hover: hover)" /> <CustomCursor client:media="(pointer: fine) and (hover: hover)" />
<GridOverlay /> <GridOverlay />
@ -188,3 +180,4 @@ const {
</script> </script>
</body> </body>
</html> </html>

View File

@ -103,7 +103,7 @@ const articleSchema = {
<div class="lg:col-span-8 lg:col-start-3"> <div class="lg:col-span-8 lg:col-start-3">
<!-- Back Navigation --> <!-- Back Navigation -->
<div class="mb-12"> <div class="mb-12">
<a href="/blog" class="inline-flex items-center gap-3 px-5 py-3 border border-[var(--theme-text-subtle)] bg-[var(--theme-overlay)] text-xs font-mono font-bold uppercase tracking-widest text-[var(--theme-text-secondary)] hover:border-brand-accent hover:text-[var(--theme-text-primary)] hover:bg-brand-accent/5 transition-all duration-300 group backdrop-blur-sm"> <a href="/blog" class="inline-flex items-center gap-3 px-5 py-3 border border-slate-700 bg-brand-dark/50 text-xs font-mono font-bold uppercase tracking-widest text-slate-400 hover:border-brand-accent hover:text-white hover:bg-brand-accent/5 transition-all duration-300 group backdrop-blur-sm">
<span class="text-brand-accent group-hover:-translate-x-1 transition-transform duration-300">&lt;</span> <span class="text-brand-accent group-hover:-translate-x-1 transition-transform duration-300">&lt;</span>
<span>RETURN_TO_ARCHIVE</span> <span>RETURN_TO_ARCHIVE</span>
</a> </a>
@ -115,30 +115,30 @@ const articleSchema = {
<!-- Text Content --> <!-- Text Content -->
<div class="order-2 lg:order-1 relative z-10"> <div class="order-2 lg:order-1 relative z-10">
<!-- Metadata --> <!-- Metadata -->
<div class="flex flex-wrap items-center gap-4 text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest mb-8 border-b border-[var(--theme-border-primary)] pb-4"> <div class="flex flex-wrap items-center gap-4 text-[10px] font-mono text-slate-500 uppercase tracking-widest mb-8 border-b border-white/10 pb-4">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<div class="w-1.5 h-1.5 bg-brand-accent shadow-[0_0_10px_rgba(221,65,50,0.5)] rounded-full animate-pulse"></div> <div class="w-1.5 h-1.5 bg-brand-accent shadow-[0_0_10px_rgba(221,65,50,0.5)] rounded-full animate-pulse"></div>
<span class="text-brand-accent font-bold">SYS.LOG</span> <span class="text-brand-accent font-bold">SYS.LOG</span>
</div> </div>
<span class="text-[var(--theme-text-subtle)]">/</span> <span class="text-slate-700">/</span>
<FormattedDate date={pubDate} /> <FormattedDate date={pubDate} />
<span class="text-[var(--theme-text-subtle)]">/</span> <span class="text-slate-700">/</span>
<span>{readTime}</span> <span>{readTime}</span>
</div> </div>
{category && ( {category && (
<div class="mb-6"> <div class="mb-6">
<span class="inline-block px-3 py-1.5 text-[10px] font-mono font-bold uppercase tracking-[0.2em] bg-[var(--theme-hover-bg-strong)] border border-[var(--theme-border-primary)] text-brand-accent hover:bg-brand-accent/10 transition-colors cursor-default"> <span class="inline-block px-3 py-1.5 text-[10px] font-mono font-bold uppercase tracking-[0.2em] bg-white/5 border border-white/10 text-brand-accent hover:bg-brand-accent/10 transition-colors cursor-default">
/// {category} /// {category}
</span> </span>
</div> </div>
)} )}
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-[var(--theme-text-primary)] uppercase leading-[0.9] tracking-tighter mb-8 break-words text-balance"> <h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-white uppercase leading-[0.9] tracking-tighter mb-8 break-words text-balance">
{title} {title}
</h1> </h1>
<p class="text-base md:text-lg text-[var(--theme-text-secondary)] leading-relaxed font-light mb-8 border-l-2 border-brand-accent pl-6"> <p class="text-base md:text-lg text-slate-400 leading-relaxed font-light mb-8 border-l-2 border-brand-accent pl-6">
{description} {description}
</p> </p>
@ -146,7 +146,7 @@ const articleSchema = {
{tags && tags.length > 0 && ( {tags && tags.length > 0 && (
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
{tags.map((tag) => ( {tags.map((tag) => (
<span class="px-2 py-1 text-[9px] font-mono uppercase bg-[var(--theme-bg-primary)] border border-[var(--theme-border-primary)] text-[var(--theme-text-muted)] hover:border-brand-accent/50 hover:text-[var(--theme-text-primary)] transition-colors cursor-default"> <span class="px-2 py-1 text-[9px] font-mono uppercase bg-brand-dark border border-slate-800 text-slate-500 hover:border-brand-accent/50 hover:text-white transition-colors cursor-default">
#{tag} #{tag}
</span> </span>
))} ))}
@ -157,7 +157,7 @@ const articleSchema = {
<!-- Hero Image --> <!-- Hero Image -->
{heroImage && ( {heroImage && (
<div class="order-1 lg:order-2"> <div class="order-1 lg:order-2">
<div class="relative aspect-[4/3] lg:aspect-square overflow-hidden border border-[var(--theme-border-primary)] bg-[var(--theme-hover-bg)] group"> <div class="relative aspect-[4/3] lg:aspect-square overflow-hidden border border-white/10 bg-white/[0.02] group">
<!-- Tech corners --> <!-- Tech corners -->
<div class="absolute top-0 left-0 w-2 h-2 border-t border-l border-brand-accent z-20"></div> <div class="absolute top-0 left-0 w-2 h-2 border-t border-l border-brand-accent z-20"></div>
<div class="absolute top-0 right-0 w-2 h-2 border-t border-r border-brand-accent z-20"></div> <div class="absolute top-0 right-0 w-2 h-2 border-t border-r border-brand-accent z-20"></div>
@ -188,30 +188,30 @@ const articleSchema = {
</div> </div>
<!-- Author Footer --> <!-- Author Footer -->
<footer class="mt-24 pt-10 border-t border-[var(--theme-border-primary)]"> <footer class="mt-24 pt-10 border-t border-white/10">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-6"> <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-6">
<div> <div>
<p class="text-[10px] font-mono text-brand-accent uppercase tracking-widest mb-2 flex items-center gap-2"> <p class="text-[10px] font-mono text-brand-accent uppercase tracking-widest mb-2 flex items-center gap-2">
<span class="w-1.5 h-1.5 bg-brand-accent rounded-full animate-pulse"></span> <span class="w-1.5 h-1.5 bg-brand-accent rounded-full animate-pulse"></span>
/// END TRANSMISSION /// END TRANSMISSION
</p> </p>
<p class="text-[var(--theme-text-secondary)] text-sm font-mono"> <p class="text-slate-400 text-sm font-mono">
LOG_DATE: <FormattedDate date={pubDate} /> LOG_DATE: <FormattedDate date={pubDate} />
{updatedDate && ( {updatedDate && (
<span class="text-[var(--theme-text-muted)]"> // UPDATED: <FormattedDate date={updatedDate} /></span> <span class="text-slate-500"> // UPDATED: <FormattedDate date={updatedDate} /></span>
)} )}
</p> </p>
</div> </div>
<!-- Share Links --> <!-- Share Links -->
<div class="flex items-center gap-6"> <div class="flex items-center gap-6">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest">DATA_UPLINK:</span> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest">DATA_UPLINK:</span>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<a <a
href={`https://twitter.com/intent/tweet?text=${encodeURIComponent(title)}&url=${encodeURIComponent(Astro.url.href)}`} href={`https://twitter.com/intent/tweet?text=${encodeURIComponent(title)}&url=${encodeURIComponent(Astro.url.href)}`}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="w-10 h-10 flex items-center justify-center border border-[var(--theme-border-primary)] text-[var(--theme-text-secondary)] hover:border-brand-accent hover:text-brand-accent transition-all duration-300" class="w-10 h-10 flex items-center justify-center border border-white/10 text-slate-400 hover:border-brand-accent hover:text-brand-accent transition-all duration-300"
aria-label="Share on Twitter" aria-label="Share on Twitter"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@ -222,7 +222,7 @@ const articleSchema = {
href={`https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(Astro.url.href)}&title=${encodeURIComponent(title)}`} href={`https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(Astro.url.href)}&title=${encodeURIComponent(title)}`}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="w-10 h-10 flex items-center justify-center border border-[var(--theme-border-primary)] text-[var(--theme-text-secondary)] hover:border-brand-accent hover:text-brand-accent transition-all duration-300" class="w-10 h-10 flex items-center justify-center border border-white/10 text-slate-400 hover:border-brand-accent hover:text-brand-accent transition-all duration-300"
aria-label="Share on LinkedIn" aria-label="Share on LinkedIn"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@ -234,7 +234,7 @@ const articleSchema = {
<button <button
type="button" type="button"
onclick="navigator.clipboard.writeText(window.location.href)" onclick="navigator.clipboard.writeText(window.location.href)"
class="w-10 h-10 flex items-center justify-center border border-[var(--theme-border-primary)] text-[var(--theme-text-secondary)] hover:border-brand-accent hover:text-brand-accent transition-all duration-300" class="w-10 h-10 flex items-center justify-center border border-white/10 text-slate-400 hover:border-brand-accent hover:text-brand-accent transition-all duration-300"
aria-label="Copy link" aria-label="Copy link"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@ -254,8 +254,8 @@ const articleSchema = {
<RelatedPosts posts={relatedPosts} /> <RelatedPosts posts={relatedPosts} />
<!-- Back to Blog --> <!-- Back to Blog -->
<div class="mt-20 pt-10 border-t border-[var(--theme-border-primary)] flex justify-center lg:justify-start"> <div class="mt-20 pt-10 border-t border-white/10 flex justify-center lg:justify-start">
<a href="/blog" class="inline-flex items-center gap-4 px-8 py-4 border border-[var(--theme-border-strong)] text-xs font-bold uppercase tracking-widest text-[var(--theme-text-primary)] hover:border-brand-accent hover:bg-brand-accent hover:text-brand-dark transition-all duration-300 group"> <a href="/blog" class="inline-flex items-center gap-4 px-8 py-4 border border-slate-600 text-xs font-bold uppercase tracking-widest text-white hover:border-brand-accent hover:bg-brand-accent hover:text-brand-dark transition-all duration-300 group">
<span class="font-mono transition-transform duration-300 group-hover:-translate-x-1">&lt;</span> <span class="font-mono transition-transform duration-300 group-hover:-translate-x-1">&lt;</span>
ACCESS_FULL_ARCHIVE ACCESS_FULL_ARCHIVE
</a> </a>

View File

@ -31,7 +31,7 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
<section class="container mx-auto px-6 lg:px-12"> <section class="container mx-auto px-6 lg:px-12">
<!-- Back Navigation --> <!-- Back Navigation -->
<div class="mb-12"> <div class="mb-12">
<a href="/" class="inline-flex items-center gap-3 px-5 py-3 border border-[var(--theme-border-primary)] bg-[var(--theme-overlay)] text-xs font-mono font-bold uppercase tracking-widest text-[var(--theme-text-secondary)] hover:border-brand-accent hover:text-[var(--theme-text-primary)] hover:bg-brand-accent/5 transition-all duration-300 group backdrop-blur-sm"> <a href="/" class="inline-flex items-center gap-3 px-5 py-3 border border-slate-700 bg-brand-dark/50 text-xs font-mono font-bold uppercase tracking-widest text-slate-400 hover:border-brand-accent hover:text-white hover:bg-brand-accent/5 transition-all duration-300 group backdrop-blur-sm">
<span class="text-brand-accent group-hover:-translate-x-1 transition-transform duration-300">&lt;</span> <span class="text-brand-accent group-hover:-translate-x-1 transition-transform duration-300">&lt;</span>
<span>RETURN_TO_HOME</span> <span>RETURN_TO_HOME</span>
</a> </a>
@ -40,21 +40,14 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
<!-- Page Header --> <!-- Page Header -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-12 mb-16 lg:mb-24"> <div class="grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-12 mb-16 lg:mb-24">
<div class="lg:col-span-8"> <div class="lg:col-span-8">
<div class="flex items-center gap-3 mb-6"> <h1 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85]">
<div class="w-2 h-2 bg-brand-accent animate-pulse"></div> <span class="block text-white animate-on-scroll slide-up">BLOG</span>
<span class="font-mono text-[10px] uppercase tracking-[0.3em] text-brand-accent">SYS.LOG /// PRODUCTION_ARCHIVE</span> <span class="block text-transparent text-stroke animate-on-scroll slide-up stagger-1">ARCHIVE</span>
</div>
<h1 class="text-5xl md:text-7xl lg:text-8xl font-bold uppercase tracking-tighter leading-[0.85]">
<span class="block text-[var(--theme-text-primary)]">BLOG</span>
<span class="block text-brand-accent">ARCHIVE</span>
</h1> </h1>
</div> </div>
<div class="lg:col-span-4 flex flex-col justify-end"> <div class="lg:col-span-4 flex flex-col justify-end pb-4">
<div class="font-mono text-[10px] text-[var(--theme-text-subtle)] uppercase tracking-widest mb-4 flex items-center gap-2"> <div class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">/// THOUGHTS & PROCESS</div>
<span class="w-8 h-px bg-brand-accent/30"></span> <p class="text-slate-400 text-base leading-relaxed border-l border-brand-accent pl-6 animate-on-scroll fade-in stagger-2">
THOUGHTS & PROCESS
</div>
<p class="text-[var(--theme-text-secondary)] text-lg leading-relaxed border-l border-brand-accent/30 pl-6">
Deep dives into VFX production, technical pipelines, and creative process. Sharing lessons from the front lines of visual effects. Deep dives into VFX production, technical pipelines, and creative process. Sharing lessons from the front lines of visual effects.
</p> </p>
</div> </div>
@ -68,10 +61,10 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
<span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest font-bold"> <span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest font-bold">
SYS.BLOG /// FEATURED SYS.BLOG /// FEATURED
</span> </span>
<span class="h-px flex-grow bg-[var(--theme-border-secondary)]"></span> <span class="h-px flex-grow bg-white/10"></span>
</div> </div>
<article class="group relative border border-[var(--theme-border-primary)] bg-[var(--theme-hover-bg)] hover:border-brand-accent/40 transition-all duration-500 overflow-hidden"> <article class="group relative border border-white/10 bg-white/[0.02] hover:border-brand-accent/40 transition-all duration-500 overflow-hidden">
<!-- Accent indicator strip --> <!-- Accent indicator strip -->
<div class="absolute top-0 left-0 w-1 h-full bg-brand-accent"></div> <div class="absolute top-0 left-0 w-1 h-full bg-brand-accent"></div>
<div class="absolute top-0 left-0 w-full h-1 bg-brand-accent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div class="absolute top-0 left-0 w-full h-1 bg-brand-accent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
@ -88,14 +81,14 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
class="w-full h-full object-cover transition-transform duration-[1.2s] ease-out group-hover:scale-105" class="w-full h-full object-cover transition-transform duration-[1.2s] ease-out group-hover:scale-105"
/> />
)} )}
<div class="absolute inset-0 bg-[var(--theme-card-overlay)] group-hover:opacity-50 transition-opacity duration-500"></div> <div class="absolute inset-0 bg-brand-dark/30 group-hover:bg-brand-dark/10 transition-colors duration-500"></div>
<div class="absolute inset-0 bg-gradient-to-r from-transparent via-transparent to-[var(--theme-card-gradient)] hidden lg:block"></div> <div class="absolute inset-0 bg-gradient-to-r from-transparent via-transparent to-brand-dark/80 hidden lg:block"></div>
<div class="absolute inset-0 bg-gradient-to-t from-[var(--theme-card-gradient)] to-transparent lg:hidden"></div> <div class="absolute inset-0 bg-gradient-to-t from-brand-dark/60 to-transparent lg:hidden"></div>
<!-- Category badge --> <!-- Category badge -->
{featuredPost.data.category && ( {featuredPost.data.category && (
<div class="absolute top-6 left-6"> <div class="absolute top-6 left-6">
<span class="px-4 py-2 text-[10px] font-mono font-bold uppercase tracking-widest bg-[var(--theme-overlay)] border border-brand-accent/50 text-brand-accent backdrop-blur-sm"> <span class="px-4 py-2 text-[10px] font-mono font-bold uppercase tracking-widest bg-brand-dark/80 border border-brand-accent/50 text-brand-accent backdrop-blur-sm">
{featuredPost.data.category} {featuredPost.data.category}
</span> </span>
</div> </div>
@ -112,21 +105,21 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
<span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest"> <span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest">
<FormattedDate date={featuredPost.data.pubDate} /> <FormattedDate date={featuredPost.data.pubDate} />
</span> </span>
<span class="h-px w-8 bg-[var(--theme-border-strong)]"></span> <span class="h-px w-8 bg-white/20"></span>
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest">
5 min read 5 min read
</span> </span>
</div> </div>
<!-- Title --> <!-- Title -->
<a href={`/blog/${featuredPost.id}/`}> <a href={`/blog/${featuredPost.id}/`}>
<h2 class="text-3xl lg:text-4xl xl:text-5xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tight mb-6 group-hover:text-brand-accent transition-colors duration-300 leading-tight"> <h2 class="text-3xl lg:text-4xl xl:text-5xl font-bold text-white uppercase tracking-tight mb-6 group-hover:text-brand-accent transition-colors duration-300 leading-tight">
{featuredPost.data.title} {featuredPost.data.title}
</h2> </h2>
</a> </a>
<!-- Description --> <!-- Description -->
<p class="text-[var(--theme-text-secondary)] text-base lg:text-lg font-light leading-relaxed mb-8 line-clamp-3"> <p class="text-slate-400 text-base lg:text-lg font-light leading-relaxed mb-8 line-clamp-3">
{featuredPost.data.description} {featuredPost.data.description}
</p> </p>
@ -134,7 +127,7 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
{featuredPost.data.tags && featuredPost.data.tags.length > 0 && ( {featuredPost.data.tags && featuredPost.data.tags.length > 0 && (
<div class="flex flex-wrap gap-2 mb-8"> <div class="flex flex-wrap gap-2 mb-8">
{featuredPost.data.tags.slice(0, 5).map((tag: string) => ( {featuredPost.data.tags.slice(0, 5).map((tag: string) => (
<span class="px-3 py-1.5 text-[10px] font-mono uppercase border border-[var(--theme-border-primary)] text-[var(--theme-text-muted)] group-hover:border-[var(--theme-border-strong)] transition-colors"> <span class="px-3 py-1.5 text-[10px] font-mono uppercase border border-white/10 text-slate-500 group-hover:border-white/20 transition-colors">
{tag} {tag}
</span> </span>
))} ))}
@ -142,13 +135,13 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
)} )}
<!-- Read link --> <!-- Read link -->
<div class="pt-6 border-t border-[var(--theme-border-primary)]"> <div class="pt-6 border-t border-white/10">
<a <a
href={`/blog/${featuredPost.id}/`} href={`/blog/${featuredPost.id}/`}
class="inline-flex items-center gap-4 text-xs font-bold uppercase tracking-widest text-[var(--theme-text-primary)] hover:text-brand-accent transition-all duration-300 group/link" class="inline-flex items-center gap-4 text-xs font-bold uppercase tracking-widest text-white hover:text-brand-accent transition-all duration-300 group/link"
> >
Read Full Article Read Full Article
<span class="block w-8 h-[1px] bg-[var(--theme-border-strong)] group-hover/link:bg-brand-accent group-hover/link:w-12 transition-all duration-300"></span> <span class="block w-8 h-[1px] bg-white/30 group-hover/link:bg-brand-accent group-hover/link:w-12 transition-all duration-300"></span>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="14" width="14"
@ -175,10 +168,10 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
<!-- Latest Section with Filters --> <!-- Latest Section with Filters -->
<div class="mb-16 lg:mb-24"> <div class="mb-16 lg:mb-24">
<div class="flex items-center gap-4 mb-8"> <div class="flex items-center gap-4 mb-8">
<span class="text-[10px] font-mono text-[var(--theme-text-muted)] uppercase tracking-widest font-bold"> <span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest font-bold">
/// LATEST TRANSMISSIONS /// LATEST TRANSMISSIONS
</span> </span>
<span class="h-px flex-grow bg-[var(--theme-border-secondary)]"></span> <span class="h-px flex-grow bg-white/10"></span>
</div> </div>
<!-- Filters Component --> <!-- Filters Component -->
@ -209,10 +202,10 @@ const categories = [...new Set(allPosts.map((post) => post.data.category).filter
<!-- Empty state (hidden by default, shown via JS when no results) --> <!-- Empty state (hidden by default, shown via JS when no results) -->
<div id="no-results" class="hidden text-center py-20"> <div id="no-results" class="hidden text-center py-20">
<div class="text-[var(--theme-text-muted)] font-mono text-sm uppercase tracking-widest mb-4"> <div class="text-slate-500 font-mono text-sm uppercase tracking-widest mb-4">
/// NO MATCHING ARTICLES FOUND /// NO MATCHING ARTICLES FOUND
</div> </div>
<p class="text-[var(--theme-text-secondary)] text-sm"> <p class="text-slate-400 text-sm">
Try adjusting your search or filter criteria. Try adjusting your search or filter criteria.
</p> </p>
</div> </div>

View File

@ -16,7 +16,7 @@ const contactContent = contactEntry.data;
<div class="fixed inset-0 z-0 pointer-events-none"> <div class="fixed inset-0 z-0 pointer-events-none">
<div class="w-full h-full grid grid-cols-12 gap-4 opacity-[0.03]"> <div class="w-full h-full grid grid-cols-12 gap-4 opacity-[0.03]">
{Array.from({ length: 12 }).map((_) => ( {Array.from({ length: 12 }).map((_) => (
<div class="h-full border-r border-[var(--theme-text-primary)]"></div> <div class="h-full border-r border-white"></div>
))} ))}
</div> </div>
</div> </div>
@ -24,15 +24,15 @@ const contactContent = contactEntry.data;
<section class="relative z-10 min-h-screen flex flex-col pt-32 lg:pt-48 pb-20 px-6 lg:px-12"> <section class="relative z-10 min-h-screen flex flex-col pt-32 lg:pt-48 pb-20 px-6 lg:px-12">
<!-- Page Header --> <!-- Page Header -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-20 lg:mb-32 border-b border-[var(--theme-border-primary)] pb-12"> <div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-20 lg:mb-32 border-b border-white/10 pb-12">
<div class="lg:col-span-8"> <div class="lg:col-span-8">
<h1 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-[var(--theme-text-primary)] mb-8"> <h1 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white mb-8">
<span class="block animate-on-scroll slide-up">{contactContent.pageTitleLine1}</span> <span class="block animate-on-scroll slide-up">{contactContent.pageTitleLine1}</span>
<span class="block text-brand-accent animate-on-scroll slide-up stagger-1">{contactContent.pageTitleLine2}</span> <span class="block text-brand-accent animate-on-scroll slide-up stagger-1">{contactContent.pageTitleLine2}</span>
</h1> </h1>
</div> </div>
<div class="lg:col-span-4 flex flex-col justify-end"> <div class="lg:col-span-4 flex flex-col justify-end">
<p class="font-mono text-sm text-[var(--theme-text-secondary)] leading-relaxed mb-8 border-l border-brand-accent pl-6 animate-on-scroll fade-in stagger-2"> <p class="font-mono text-sm text-slate-400 leading-relaxed mb-8 border-l border-brand-accent pl-6 animate-on-scroll fade-in stagger-2">
{contactContent.availabilityText} {contactContent.availabilityText}
</p> </p>
</div> </div>
@ -53,11 +53,11 @@ const contactContent = contactEntry.data;
type="text" type="text"
id="name" id="name"
name="name" name="name"
class="block w-full bg-transparent border-b border-[var(--theme-border-strong)] py-4 text-xl text-[var(--theme-text-primary)] focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer" class="block w-full bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer"
placeholder="Name" placeholder="Name"
required required
/> />
<label for="name" class="absolute left-0 top-4 text-[var(--theme-text-muted)] text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-[var(--theme-text-secondary)] pointer-events-none"> <label for="name" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-slate-400 pointer-events-none">
{contactContent.formLabels?.name} {contactContent.formLabels?.name}
</label> </label>
</div> </div>
@ -67,11 +67,11 @@ const contactContent = contactEntry.data;
type="email" type="email"
id="email" id="email"
name="email" name="email"
class="block w-full bg-transparent border-b border-[var(--theme-border-strong)] py-4 text-xl text-[var(--theme-text-primary)] focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer" class="block w-full bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer"
placeholder="Email" placeholder="Email"
required required
/> />
<label for="email" class="absolute left-0 top-4 text-[var(--theme-text-muted)] text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-[var(--theme-text-secondary)] pointer-events-none"> <label for="email" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-slate-400 pointer-events-none">
{contactContent.formLabels?.email} {contactContent.formLabels?.email}
</label> </label>
</div> </div>
@ -80,22 +80,22 @@ const contactContent = contactEntry.data;
<div class="group relative" id="custom-select"> <div class="group relative" id="custom-select">
<input type="hidden" name="subject" id="subject-input" required> <input type="hidden" name="subject" id="subject-input" required>
<button type="button" id="select-trigger" class="block w-full text-left bg-transparent border-b border-[var(--theme-border-strong)] py-4 text-xl text-[var(--theme-text-primary)] focus:outline-none focus:border-brand-accent transition-colors duration-300 flex justify-between items-center group-hover:border-[var(--theme-border-primary)]"> <button type="button" id="select-trigger" class="block w-full text-left bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 flex justify-between items-center group-hover:border-white/40">
<span id="select-value" class="text-transparent">Select</span> <!-- Hidden placeholder text to keep height --> <span id="select-value" class="text-transparent">Select</span> <!-- Hidden placeholder text to keep height -->
<div class="text-brand-accent transform transition-transform duration-300" id="select-arrow"> <div class="text-brand-accent transform transition-transform duration-300" id="select-arrow">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
</div> </div>
</button> </button>
<label id="select-label" class="absolute left-0 top-4 text-[var(--theme-text-muted)] text-sm font-mono uppercase tracking-widest transition-all duration-300 pointer-events-none"> <label id="select-label" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 pointer-events-none">
{contactContent.formLabels?.subject} {contactContent.formLabels?.subject}
</label> </label>
<!-- Dropdown Menu --> <!-- Dropdown Menu -->
<div id="select-options" class="absolute left-0 top-full w-full bg-[var(--theme-bg-primary)] border border-[var(--theme-border-strong)] shadow-2xl z-50 hidden opacity-0 transform translate-y-2 transition-all duration-200 origin-top mt-2"> <div id="select-options" class="absolute left-0 top-full w-full bg-brand-dark border border-white/20 shadow-2xl z-50 hidden opacity-0 transform translate-y-2 transition-all duration-200 origin-top mt-2">
<div class="p-1"> <div class="p-1">
{contactContent.subjectOptions?.map((option) => ( {contactContent.subjectOptions?.map((option) => (
<div class="option px-5 py-4 hover:bg-[var(--theme-hover-bg-strong)] cursor-pointer text-[var(--theme-text-primary)] text-lg font-light transition-colors flex items-center gap-3 group/option" data-value={option.value}> <div class="option px-5 py-4 hover:bg-white/5 cursor-pointer text-white text-lg font-light transition-colors flex items-center gap-3 group/option" data-value={option.value}>
<span class="w-1.5 h-1.5 rounded-full bg-brand-accent opacity-0 group-hover/option:opacity-100 transition-opacity"></span> <span class="w-1.5 h-1.5 rounded-full bg-brand-accent opacity-0 group-hover/option:opacity-100 transition-opacity"></span>
{option.label} {option.label}
</div> </div>
@ -109,19 +109,19 @@ const contactContent = contactEntry.data;
id="message" id="message"
name="message" name="message"
rows="4" rows="4"
class="block w-full bg-transparent border-b border-[var(--theme-border-strong)] py-4 text-xl text-[var(--theme-text-primary)] focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer resize-none" class="block w-full bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer resize-none"
placeholder="Message" placeholder="Message"
required required
></textarea> ></textarea>
<label for="message" class="absolute left-0 top-4 text-[var(--theme-text-muted)] text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-[var(--theme-text-secondary)] pointer-events-none"> <label for="message" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-slate-400 pointer-events-none">
{contactContent.formLabels?.message} {contactContent.formLabels?.message}
</label> </label>
</div> </div>
<div class="pt-8"> <div class="pt-8">
<button type="submit" id="submit-btn" class="group relative inline-flex items-center justify-center gap-4 px-8 py-4 bg-transparent border border-[var(--theme-border-strong)] hover:border-brand-accent hover:bg-brand-accent/5 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed"> <button type="submit" id="submit-btn" class="group relative inline-flex items-center justify-center gap-4 px-8 py-4 bg-transparent border border-white/20 hover:border-brand-accent hover:bg-brand-accent/5 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed">
<span id="submit-text" data-default-text={contactContent.formLabels?.submit} class="font-mono text-xs font-bold uppercase tracking-widest text-[var(--theme-text-primary)] group-hover:text-brand-accent transition-colors">{contactContent.formLabels?.submit}</span> <span id="submit-text" data-default-text={contactContent.formLabels?.submit} class="font-mono text-xs font-bold uppercase tracking-widest text-white group-hover:text-brand-accent transition-colors">{contactContent.formLabels?.submit}</span>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-[var(--theme-text-muted)] group-hover:text-brand-accent group-hover:translate-x-1 transition-all"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-slate-500 group-hover:text-brand-accent group-hover:translate-x-1 transition-all"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button> </button>
</div> </div>
</form> </form>
@ -131,19 +131,19 @@ const contactContent = contactEntry.data;
<div class="lg:col-span-5 space-y-16 animate-on-scroll slide-left stagger-4"> <div class="lg:col-span-5 space-y-16 animate-on-scroll slide-left stagger-4">
<!-- Data Block 1 --> <!-- Data Block 1 -->
<div class="relative pl-6 border-l border-[var(--theme-border-primary)]"> <div class="relative pl-6 border-l border-white/10">
<h3 class="font-mono text-xs text-[var(--theme-text-muted)] uppercase tracking-widest mb-4">Direct Link</h3> <h3 class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">Direct Link</h3>
<a href={`mailto:${contactContent.email}`} class="text-2xl md:text-3xl font-bold text-[var(--theme-text-primary)] hover:text-brand-accent transition-colors break-all"> <a href={`mailto:${contactContent.email}`} class="text-2xl md:text-3xl font-bold text-white hover:text-brand-accent transition-colors break-all">
{contactContent.email} {contactContent.email}
</a> </a>
</div> </div>
<!-- Data Block 2 --> <!-- Data Block 2 -->
<div class="relative pl-6 border-l border-[var(--theme-border-primary)]"> <div class="relative pl-6 border-l border-white/10">
<h3 class="font-mono text-xs text-[var(--theme-text-muted)] uppercase tracking-widest mb-4">Coordinates</h3> <h3 class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">Coordinates</h3>
<p class="text-xl text-[var(--theme-text-primary)] font-light"> <p class="text-xl text-white font-light">
{contactContent.location}<br> {contactContent.location}<br>
<span class="text-[var(--theme-text-muted)] text-base">{contactContent.locationCountry}</span> <span class="text-slate-500 text-base">{contactContent.locationCountry}</span>
</p> </p>
<div class="mt-4 font-mono text-xs text-brand-accent"> <div class="mt-4 font-mono text-xs text-brand-accent">
{contactContent.coordinates} {contactContent.coordinates}
@ -151,14 +151,14 @@ const contactContent = contactEntry.data;
</div> </div>
<!-- Data Block 3 --> <!-- Data Block 3 -->
<div class="relative pl-6 border-l border-[var(--theme-border-primary)]"> <div class="relative pl-6 border-l border-white/10">
<h3 class="font-mono text-xs text-[var(--theme-text-muted)] uppercase tracking-widest mb-4">Social Feed</h3> <h3 class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">Social Feed</h3>
<ul class="space-y-4"> <ul class="space-y-4">
{contactContent.socialLinks?.map((link) => ( {contactContent.socialLinks?.map((link) => (
<li> <li>
<a href={link.url} class="flex items-center gap-4 group"> <a href={link.url} class="flex items-center gap-4 group">
<span class="text-[var(--theme-text-secondary)] group-hover:text-[var(--theme-text-primary)] transition-colors text-lg">{link.name}</span> <span class="text-slate-400 group-hover:text-white transition-colors text-lg">{link.name}</span>
<svg class="w-4 h-4 text-[var(--theme-text-subtle)] group-hover:text-brand-accent transition-colors transform group-hover:translate-x-1 group-hover:-translate-y-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg> <svg class="w-4 h-4 text-slate-600 group-hover:text-brand-accent transition-colors transform group-hover:translate-x-1 group-hover:-translate-y-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>
</a> </a>
</li> </li>
))} ))}
@ -174,7 +174,7 @@ const contactContent = contactEntry.data;
<div id="toast-container" class="fixed top-6 right-6 z-50 pointer-events-none"></div> <div id="toast-container" class="fixed top-6 right-6 z-50 pointer-events-none"></div>
<!-- Full-Screen Modal for Loading and Response --> <!-- Full-Screen Modal for Loading and Response -->
<div id="transmission-modal" class="fixed inset-0 z-[100] flex items-center justify-center bg-[var(--theme-overlay-heavy)] backdrop-blur-xl opacity-0 pointer-events-none transition-opacity duration-500"> <div id="transmission-modal" class="fixed inset-0 z-[100] flex items-center justify-center bg-brand-dark/95 backdrop-blur-xl opacity-0 pointer-events-none transition-opacity duration-500">
<!-- Loading State --> <!-- Loading State -->
<div id="loading-state" class="text-center"> <div id="loading-state" class="text-center">
@ -200,7 +200,7 @@ const contactContent = contactEntry.data;
<!-- Loading Text --> <!-- Loading Text -->
<div class="space-y-4"> <div class="space-y-4">
<h2 class="text-3xl md:text-5xl font-bold text-[var(--theme-text-primary)] uppercase tracking-tight"> <h2 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tight">
<span id="loading-text">Transmitting</span> <span id="loading-text">Transmitting</span>
</h2> </h2>
<div class="flex items-center justify-center gap-2"> <div class="flex items-center justify-center gap-2">
@ -208,15 +208,15 @@ const contactContent = contactEntry.data;
<div class="w-2 h-2 bg-brand-accent rounded-full animate-bounce delay-100"></div> <div class="w-2 h-2 bg-brand-accent rounded-full animate-bounce delay-100"></div>
<div class="w-2 h-2 bg-brand-accent rounded-full animate-bounce delay-200"></div> <div class="w-2 h-2 bg-brand-accent rounded-full animate-bounce delay-200"></div>
</div> </div>
<p class="font-mono text-sm text-[var(--theme-text-secondary)] uppercase tracking-widest">Signal Processing</p> <p class="font-mono text-sm text-slate-400 uppercase tracking-widest">Signal Processing</p>
</div> </div>
</div> </div>
<!-- Response State (hidden initially) --> <!-- Response State (hidden initially) -->
<div id="response-state" class="hidden w-full h-full absolute inset-0 z-10 flex flex-col items-center justify-center p-6 opacity-0 transition-all duration-700"> <div id="response-state" class="hidden w-full h-full absolute inset-0 z-10 flex flex-col items-center justify-center p-6 opacity-0 transition-all duration-700">
<!-- Close button --> <!-- Close button -->
<button id="close-modal" class="absolute top-8 right-8 z-50 p-3 border border-[var(--theme-border-strong)] hover:border-brand-accent hover:bg-brand-accent/10 transition-all duration-300 group"> <button id="close-modal" class="absolute top-8 right-8 z-50 p-3 border border-white/20 hover:border-brand-accent hover:bg-brand-accent/10 transition-all duration-300 group">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-[var(--theme-text-primary)] group-hover:text-brand-accent transition-colors"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-white group-hover:text-brand-accent transition-colors">
<line x1="18" y1="6" x2="6" y2="18"></line> <line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line>
</svg> </svg>
@ -251,15 +251,15 @@ const contactContent = contactEntry.data;
</BaseLayout> </BaseLayout>
<style> <style>
/* Custom autofill styles to match theme */ /* Custom autofill styles to match dark theme */
input:-webkit-autofill, input:-webkit-autofill,
input:-webkit-autofill:hover, input:-webkit-autofill:hover,
input:-webkit-autofill:focus, input:-webkit-autofill:focus,
textarea:-webkit-autofill, textarea:-webkit-autofill,
textarea:-webkit-autofill:hover, textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus { textarea:-webkit-autofill:focus {
-webkit-text-fill-color: var(--theme-text-primary); -webkit-text-fill-color: white;
-webkit-box-shadow: 0 0 0px 1000px var(--theme-bg-primary) inset; -webkit-box-shadow: 0 0 0px 1000px #0B0D11 inset;
transition: background-color 5000s ease-in-out 0s; transition: background-color 5000s ease-in-out 0s;
} }
@ -267,13 +267,13 @@ const contactContent = contactEntry.data;
.label-active { .label-active {
top: -1.5rem !important; top: -1.5rem !important;
font-size: 0.75rem !important; font-size: 0.75rem !important;
color: var(--theme-text-secondary) !important; color: #94A3B8 !important;
} }
/* Dropdown open state */ /* Dropdown open state */
.dropdown-open #select-arrow { .dropdown-open #select-arrow {
transform: rotate(180deg); transform: rotate(180deg);
color: var(--theme-text-primary); color: white;
} }
/* Custom Animations */ /* Custom Animations */
@ -322,29 +322,28 @@ const contactContent = contactEntry.data;
} }
.custom-scrollbar::-webkit-scrollbar-track { .custom-scrollbar::-webkit-scrollbar-track {
background: var(--theme-hover-bg-strong); background: rgba(255, 255, 255, 0.05);
} }
.custom-scrollbar::-webkit-scrollbar-thumb { .custom-scrollbar::-webkit-scrollbar-thumb {
background: var(--color-brand-accent); background: rgba(0, 255, 255, 0.3);
border-radius: 4px; border-radius: 4px;
opacity: 0.3;
} }
.custom-scrollbar::-webkit-scrollbar-thumb:hover { .custom-scrollbar::-webkit-scrollbar-thumb:hover {
opacity: 0.5; background: rgba(0, 255, 255, 0.5);
} }
/* Response Content Prose Styles - Enhanced Readability */ /* Response Content Prose Styles - Enhanced Readability */
.prose-response { .prose-response {
color: var(--theme-text-primary); color: white;
text-align: left; text-align: left;
} }
.prose-response h1, .prose-response h1,
.prose-response h2, .prose-response h2,
.prose-response h3 { .prose-response h3 {
color: var(--theme-text-primary); color: white;
margin-top: 1.5em; margin-top: 1.5em;
margin-bottom: 0.75em; margin-bottom: 0.75em;
font-weight: 800; font-weight: 800;
@ -355,7 +354,7 @@ const contactContent = contactEntry.data;
.prose-response h1 { .prose-response h1 {
font-size: 3.5rem; font-size: 3.5rem;
background: linear-gradient(to right, var(--theme-text-primary), var(--theme-text-secondary)); background: linear-gradient(to right, #fff, #94a3b8);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
margin-bottom: 0.5em; margin-bottom: 0.5em;
@ -367,53 +366,53 @@ const contactContent = contactEntry.data;
.prose-response h3 { .prose-response h3 {
font-size: 1.75rem; font-size: 1.75rem;
color: var(--color-brand-accent); color: #ff4d00;
} }
.prose-response p { .prose-response p {
margin-bottom: 1.5em; margin-bottom: 1.5em;
line-height: 1.8; line-height: 1.8;
color: var(--theme-text-secondary); color: rgba(255, 255, 255, 0.9);
font-size: 1.5rem; font-size: 1.5rem; /* Increased size significantly */
font-weight: 300; font-weight: 300;
max-width: 65ch; max-width: 65ch;
margin-right: auto; margin-right: auto;
} }
.prose-response strong { .prose-response strong {
color: var(--color-brand-accent); color: #ff4d00;
font-weight: 600; font-weight: 600;
} }
.prose-response em { .prose-response em {
font-style: italic; font-style: italic;
color: var(--theme-text-muted); color: #94a3b8;
} }
/* Blockquote for signature or special text */ /* Blockquote for signature or special text */
.prose-response blockquote { .prose-response blockquote {
border-left: none; border-left: none; /* Removed standard border */
margin: 3em 0 1em; margin: 3em 0 1em;
padding: 0; padding: 0;
color: var(--color-brand-accent); color: #ff4d00;
font-family: 'Courier New', monospace; font-family: 'Courier New', monospace;
font-size: 1rem; font-size: 1rem;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.2em; letter-spacing: 0.2em;
display: inline-block; display: inline-block;
border-top: 1px solid rgba(221, 65, 50, 0.3); border-top: 1px solid rgba(255, 77, 0, 0.3);
padding-top: 2em; padding-top: 2em;
} }
.prose-response a { .prose-response a {
color: var(--color-brand-accent); color: #ff4d00;
text-decoration: underline; text-decoration: underline;
text-underline-offset: 4px; text-underline-offset: 4px;
transition: all 0.3s; transition: all 0.3s;
} }
.prose-response a:hover { .prose-response a:hover {
color: var(--theme-text-primary); color: white;
text-decoration-thickness: 2px; text-decoration-thickness: 2px;
} }
@ -462,14 +461,14 @@ const contactContent = contactEntry.data;
// Update UI // Update UI
selectValue.textContent = text; selectValue.textContent = text;
selectValue.classList.remove('text-transparent'); selectValue.classList.remove('text-transparent');
selectValue.classList.add('text-[var(--theme-text-primary)]'); selectValue.classList.add('text-white');
// Update Data // Update Data
hiddenInput.value = value; hiddenInput.value = value;
// Update Label Style // Update Label Style
selectLabel.classList.add('label-active'); selectLabel.classList.add('label-active');
selectLabel.classList.add('text-brand-accent'); selectLabel.classList.add('text-brand-accent'); // Highlight when selected
closeDropdown(); closeDropdown();
}); });

View File

@ -109,117 +109,33 @@
} }
@utility text-stroke { @utility text-stroke {
-webkit-text-stroke: 1px var(--theme-text-stroke); -webkit-text-stroke: 1px rgba(255, 255, 255, 0.15);
color: transparent;
}
@utility text-stroke-dark {
-webkit-text-stroke: 1px var(--theme-text-stroke-inverted);
color: transparent; color: transparent;
} }
@utility skill-tag { @utility skill-tag {
@apply text-[10px] font-mono font-bold uppercase tracking-wider px-3 py-2 border border-[var(--theme-border-strong)] text-[var(--theme-text-secondary)] hover:border-brand-accent hover:text-[var(--theme-text-primary)] transition-all duration-300 cursor-default select-none; @apply text-[10px] font-mono font-bold uppercase tracking-wider px-3 py-2 border border-slate-700 text-slate-400 hover:border-brand-accent hover:text-white transition-all duration-300 cursor-default select-none;
} }
@utility btn-primary { @utility btn-primary {
@apply bg-brand-accent text-brand-dark px-8 py-4 text-xs font-bold uppercase tracking-widest hover:bg-[var(--theme-text-primary)] hover:text-[var(--theme-bg-primary)] transition-all duration-300 inline-block; @apply bg-brand-accent text-brand-dark px-8 py-4 text-xs font-bold uppercase tracking-widest hover:bg-white transition-all duration-300 inline-block;
} }
@utility btn-ghost { @utility btn-ghost {
@apply border border-[var(--theme-border-strong)] text-[var(--theme-text-primary)] px-8 py-4 text-xs font-bold uppercase tracking-widest hover:border-brand-accent hover:bg-brand-accent/5 transition-all duration-300 inline-block; @apply border border-slate-600 text-white px-8 py-4 text-xs font-bold uppercase tracking-widest hover:border-brand-accent hover:bg-brand-accent/5 transition-all duration-300 inline-block;
} }
@utility grid-overlay { @utility grid-overlay {
background-size: 100px 100px; background-size: 100px 100px;
background-image: linear-gradient(to right, var(--theme-grid-line) 1px, transparent 1px); background-image: linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
pointer-events: none; pointer-events: none;
z-index: 0; z-index: 0;
} }
/* ===== THEME SYSTEM ===== */
/* Dark mode (default) */
:root {
--vh-full: 100vh;
--vh-full: 100dvh;
/* Theme colors - Dark mode defaults */
--theme-bg-primary: #0B0D11;
--theme-bg-secondary: #151921;
--theme-bg-tertiary: #1E293B;
--theme-text-primary: #ffffff;
--theme-text-secondary: #94A3B8;
--theme-text-muted: #64748B;
--theme-text-subtle: #475569;
--theme-border-primary: rgba(255, 255, 255, 0.1);
--theme-border-secondary: rgba(255, 255, 255, 0.05);
--theme-border-strong: rgba(255, 255, 255, 0.2);
--theme-overlay: rgba(11, 13, 17, 0.8);
--theme-overlay-heavy: rgba(11, 13, 17, 0.98);
--theme-grid-line: rgba(255, 255, 255, 0.03);
--theme-hover-bg: rgba(255, 255, 255, 0.02);
--theme-hover-bg-strong: rgba(255, 255, 255, 0.05);
--theme-text-stroke: rgba(255, 255, 255, 0.15);
--theme-text-stroke-inverted: rgba(0, 0, 0, 0.15);
--theme-scrollbar-track: #0B0D11;
--theme-scrollbar-thumb: #334155;
--theme-code-bg: rgba(255, 77, 0, 0.1);
--theme-blockquote-bg: linear-gradient(135deg, rgba(255, 77, 0, 0.05), rgba(21, 25, 33, 0.8));
--theme-divider: rgba(255, 255, 255, 0.1);
--theme-decorative-opacity: 0.02;
--theme-card-overlay: rgba(11, 13, 17, 0.3);
--theme-card-gradient: rgba(11, 13, 17, 0.6);
--theme-hero-gradient-top: rgba(11, 13, 17, 0.8);
--theme-hero-gradient-side: rgba(11, 13, 17, 0.4);
}
/* Light mode */
[data-theme="light"] {
--theme-bg-primary: #FAFAFA;
--theme-bg-secondary: #F1F3F5;
--theme-bg-tertiary: #E9ECEF;
--theme-text-primary: #0B0D11;
--theme-text-secondary: #475569;
--theme-text-muted: #64748B;
--theme-text-subtle: #94A3B8;
--theme-border-primary: rgba(0, 0, 0, 0.1);
--theme-border-secondary: rgba(0, 0, 0, 0.05);
--theme-border-strong: rgba(0, 0, 0, 0.15);
--theme-overlay: rgba(250, 250, 250, 0.9);
--theme-overlay-heavy: rgba(250, 250, 250, 0.98);
--theme-grid-line: rgba(0, 0, 0, 0.04);
--theme-hover-bg: rgba(0, 0, 0, 0.02);
--theme-hover-bg-strong: rgba(0, 0, 0, 0.05);
--theme-text-stroke: rgba(0, 0, 0, 0.2);
--theme-text-stroke-inverted: rgba(255, 255, 255, 0.15);
--theme-scrollbar-track: #FAFAFA;
--theme-scrollbar-thumb: #CBD5E1;
--theme-code-bg: rgba(221, 65, 50, 0.08);
--theme-blockquote-bg: linear-gradient(135deg, rgba(221, 65, 50, 0.05), rgba(241, 243, 245, 0.9));
--theme-divider: rgba(0, 0, 0, 0.08);
--theme-decorative-opacity: 0.04;
--theme-card-overlay: rgba(250, 250, 250, 0.15);
--theme-card-gradient: rgba(250, 250, 250, 0.4);
--theme-hero-gradient-top: rgba(250, 250, 250, 0.5);
--theme-hero-gradient-side: rgba(250, 250, 250, 0.2);
}
/* Theme transition for smooth switching */
html.theme-transition,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
transition: background-color 0.3s ease,
border-color 0.3s ease,
color 0.3s ease,
box-shadow 0.3s ease !important;
}
/* Base Styles */ /* Base Styles */
body { body {
background-color: var(--theme-bg-primary); background-color: var(--color-brand-dark);
color: var(--theme-text-primary); color: #ffffff;
overflow-x: hidden; overflow-x: hidden;
} }
@ -234,17 +150,23 @@ html {
} }
} }
/* Mobile viewport height fix - uses dvh with vh fallback */
:root {
--vh-full: 100vh;
--vh-full: 100dvh;
}
/* Custom Scrollbar */ /* Custom Scrollbar */
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 8px; width: 8px;
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
background: var(--theme-scrollbar-track); background: var(--color-brand-dark);
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background: var(--theme-scrollbar-thumb); background: #334155;
transition: background 0.3s ease; transition: background 0.3s ease;
} }
@ -373,7 +295,7 @@ html {
.cursor-outline { .cursor-outline {
width: 40px; width: 40px;
height: 40px; height: 40px;
border: 1px solid rgba(221, 65, 50, 0.5); border: 1px solid rgba(255, 77, 0, 0.5);
z-index: 99999; z-index: 99999;
transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1), transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1),
height 0.3s cubic-bezier(0.16, 1, 0.3, 1), height 0.3s cubic-bezier(0.16, 1, 0.3, 1),
@ -393,7 +315,7 @@ a:hover~.cursor-outline,
button:hover~.cursor-outline { button:hover~.cursor-outline {
width: 60px; width: 60px;
height: 60px; height: 60px;
background-color: rgba(221, 65, 50, 0.05); background-color: rgba(255, 77, 0, 0.05);
border-color: var(--color-brand-accent); border-color: var(--color-brand-accent);
} }
@ -426,15 +348,15 @@ a {
.hover-border-glow:hover { .hover-border-glow:hover {
border-color: var(--color-brand-accent); border-color: var(--color-brand-accent);
box-shadow: 0 0 20px rgba(221, 65, 50, 0.1); box-shadow: 0 0 20px rgba(255, 77, 0, 0.1);
} }
/* Gradient divider */ /* Gradient divider */
.divider-gradient { .divider-gradient {
background: linear-gradient(to right, background: linear-gradient(to right,
transparent, transparent,
var(--theme-divider) 20%, rgba(255, 255, 255, 0.1) 20%,
var(--theme-divider) 80%, rgba(255, 255, 255, 0.1) 80%,
transparent); transparent);
} }
@ -442,19 +364,19 @@ a {
.divider-accent { .divider-accent {
background: linear-gradient(to right, background: linear-gradient(to right,
transparent, transparent,
rgba(221, 65, 50, 0.2) 50%, rgba(255, 77, 0, 0.2) 50%,
transparent); transparent);
} }
/* ===== PROSE / MARKDOWN STYLES ===== */ /* ===== PROSE / MARKDOWN STYLES ===== */
.prose-custom { .prose-custom {
color: var(--theme-text-secondary); color: #94A3B8;
line-height: 1.8; line-height: 1.8;
font-size: 1.0625rem; font-size: 1.0625rem;
} }
.prose-custom h2 { .prose-custom h2 {
color: var(--theme-text-primary); color: #ffffff;
font-size: 1.75rem; font-size: 1.75rem;
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
@ -462,7 +384,7 @@ a {
margin-top: 3.5rem; margin-top: 3.5rem;
margin-bottom: 1.25rem; margin-bottom: 1.25rem;
padding-bottom: 0.75rem; padding-bottom: 0.75rem;
border-bottom: 1px solid var(--theme-border-primary); border-bottom: 1px solid rgba(255, 255, 255, 0.1);
position: relative; position: relative;
scroll-margin-top: 6rem; scroll-margin-top: 6rem;
} }
@ -476,7 +398,7 @@ a {
} }
.prose-custom h3 { .prose-custom h3 {
color: var(--theme-text-primary); color: #ffffff;
font-size: 1.25rem; font-size: 1.25rem;
font-weight: 600; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
@ -487,7 +409,7 @@ a {
} }
.prose-custom h4 { .prose-custom h4 {
color: var(--theme-text-primary); color: #ffffff;
font-size: 1.1rem; font-size: 1.1rem;
font-weight: 600; font-weight: 600;
margin-top: 1.5rem; margin-top: 1.5rem;
@ -507,17 +429,17 @@ a {
} }
.prose-custom a:hover { .prose-custom a:hover {
color: var(--theme-text-primary); color: #ffffff;
border-bottom-color: var(--color-brand-accent); border-bottom-color: var(--color-brand-accent);
} }
.prose-custom strong { .prose-custom strong {
color: var(--theme-text-primary); color: #ffffff;
font-weight: 600; font-weight: 600;
} }
.prose-custom em { .prose-custom em {
color: var(--theme-text-secondary); color: #CBD5E1;
font-style: italic; font-style: italic;
} }
@ -570,14 +492,14 @@ a {
.prose-custom blockquote { .prose-custom blockquote {
position: relative; position: relative;
border-left: 3px solid var(--color-brand-accent); border-left: 3px solid var(--color-brand-accent);
background: var(--theme-blockquote-bg); background: linear-gradient(135deg, rgba(255, 77, 0, 0.05), rgba(21, 25, 33, 0.8));
padding: 1.5rem 1.5rem 1.5rem 2rem; padding: 1.5rem 1.5rem 1.5rem 2rem;
margin: 2.5rem 0; margin: 2.5rem 0;
font-style: italic; font-style: italic;
color: var(--theme-text-secondary); color: #CBD5E1;
border-right: 1px solid var(--theme-border-secondary); border-right: 1px solid rgba(255, 255, 255, 0.05);
border-top: 1px solid var(--theme-border-secondary); border-top: 1px solid rgba(255, 255, 255, 0.05);
border-bottom: 1px solid var(--theme-border-secondary); border-bottom: 1px solid rgba(255, 255, 255, 0.05);
} }
.prose-custom blockquote::before { .prose-custom blockquote::before {
@ -585,7 +507,7 @@ a {
position: absolute; position: absolute;
top: -0.75rem; top: -0.75rem;
left: 1rem; left: 1rem;
background: var(--theme-bg-primary); background: var(--color-brand-dark);
padding: 0 0.5rem; padding: 0 0.5rem;
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 0.625rem; font-size: 0.625rem;
@ -606,19 +528,19 @@ a {
/* Enhanced Code - Inline */ /* Enhanced Code - Inline */
.prose-custom code { .prose-custom code {
color: var(--color-brand-accent); color: var(--color-brand-accent);
background-color: var(--theme-code-bg); background-color: rgba(255, 77, 0, 0.1);
padding: 0.2rem 0.5rem; padding: 0.2rem 0.5rem;
border-radius: 0; border-radius: 0;
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 0.85em; font-size: 0.85em;
border: 1px solid rgba(221, 65, 50, 0.2); border: 1px solid rgba(255, 77, 0, 0.2);
} }
/* Enhanced Code Blocks - Terminal Style */ /* Enhanced Code Blocks - Terminal Style */
.prose-custom pre { .prose-custom pre {
position: relative; position: relative;
background-color: var(--theme-bg-secondary); background-color: var(--color-brand-panel);
border: 1px solid var(--theme-border-primary); border: 1px solid rgba(255, 255, 255, 0.1);
padding: 0; padding: 0;
margin: 2.5rem 0; margin: 2.5rem 0;
overflow: hidden; overflow: hidden;
@ -627,14 +549,14 @@ a {
.prose-custom pre::before { .prose-custom pre::before {
content: "TERMINAL"; content: "TERMINAL";
display: block; display: block;
background: var(--theme-hover-bg); background: rgba(255, 255, 255, 0.03);
border-bottom: 1px solid var(--theme-border-primary); border-bottom: 1px solid rgba(255, 255, 255, 0.1);
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 0.625rem; font-size: 0.625rem;
font-weight: 700; font-weight: 700;
letter-spacing: 0.15em; letter-spacing: 0.15em;
color: var(--theme-text-muted); color: #64748B;
text-transform: uppercase; text-transform: uppercase;
} }
@ -642,7 +564,7 @@ a {
display: block; display: block;
background: none; background: none;
padding: 1.5rem; padding: 1.5rem;
color: var(--theme-text-secondary); color: #CBD5E1;
border: none; border: none;
overflow-x: auto; overflow-x: auto;
} }
@ -663,25 +585,25 @@ a {
content: ""; content: "";
flex: 1; flex: 1;
height: 1px; height: 1px;
background: linear-gradient(to right, transparent, rgba(221, 65, 50, 0.3)); background: linear-gradient(to right, transparent, rgba(255, 77, 0, 0.3));
} }
.prose-custom hr::after { .prose-custom hr::after {
content: ""; content: "";
flex: 1; flex: 1;
height: 1px; height: 1px;
background: linear-gradient(to left, transparent, rgba(221, 65, 50, 0.3)); background: linear-gradient(to left, transparent, rgba(255, 77, 0, 0.3));
} }
/* Enhanced Images */ /* Enhanced Images */
.prose-custom img { .prose-custom img {
border: 1px solid var(--theme-border-primary); border: 1px solid rgba(255, 255, 255, 0.1);
margin: 2.5rem 0; margin: 2.5rem 0;
transition: border-color 0.3s ease; transition: border-color 0.3s ease;
} }
.prose-custom img:hover { .prose-custom img:hover {
border-color: rgba(221, 65, 50, 0.3); border-color: rgba(255, 77, 0, 0.3);
} }
/* Image Captions (for figures) */ /* Image Captions (for figures) */
@ -698,7 +620,7 @@ a {
font-size: 0.6875rem; font-size: 0.6875rem;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.1em; letter-spacing: 0.1em;
color: var(--theme-text-muted); color: #64748B;
margin-top: 0.75rem; margin-top: 0.75rem;
padding-left: 0.5rem; padding-left: 0.5rem;
border-left: 2px solid var(--color-brand-accent); border-left: 2px solid var(--color-brand-accent);
@ -712,7 +634,7 @@ a {
.prose-custom .video-container video { .prose-custom .video-container video {
width: 100%; width: 100%;
border: 1px solid var(--theme-border-primary); border: 1px solid rgba(255, 255, 255, 0.1);
} }
.prose-custom .video-container p { .prose-custom .video-container p {
@ -720,7 +642,7 @@ a {
font-size: 0.6875rem; font-size: 0.6875rem;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.1em; letter-spacing: 0.1em;
color: var(--theme-text-muted); color: #64748B;
margin-top: 0.75rem; margin-top: 0.75rem;
margin-bottom: 0; margin-bottom: 0;
} }
@ -734,8 +656,8 @@ a {
} }
.prose-custom thead { .prose-custom thead {
background: var(--theme-hover-bg); background: rgba(255, 255, 255, 0.03);
border-bottom: 1px solid var(--theme-border-primary); border-bottom: 1px solid rgba(255, 255, 255, 0.1);
} }
.prose-custom th { .prose-custom th {
@ -744,54 +666,17 @@ a {
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.1em; letter-spacing: 0.1em;
color: var(--theme-text-muted); color: #64748B;
padding: 1rem; padding: 1rem;
text-align: left; text-align: left;
} }
.prose-custom td { .prose-custom td {
padding: 1rem; padding: 1rem;
border-bottom: 1px solid var(--theme-border-secondary); border-bottom: 1px solid rgba(255, 255, 255, 0.05);
color: var(--theme-text-secondary); color: #94A3B8;
} }
.prose-custom tr:hover td { .prose-custom tr:hover td {
background: var(--theme-hover-bg); background: rgba(255, 255, 255, 0.02);
}
/* ===== THEME-AWARE UTILITY CLASSES ===== */
/* Background colors */
.bg-theme-primary {
background-color: var(--theme-bg-primary);
}
.bg-theme-secondary {
background-color: var(--theme-bg-secondary);
}
.bg-theme-tertiary {
background-color: var(--theme-bg-tertiary);
}
/* Text colors */
.text-theme-primary {
color: var(--theme-text-primary);
}
.text-theme-secondary {
color: var(--theme-text-secondary);
}
.text-theme-muted {
color: var(--theme-text-muted);
}
/* Border colors */
.border-theme-primary {
border-color: var(--theme-border-primary);
}
.border-theme-secondary {
border-color: var(--theme-border-secondary);
} }