diff --git a/app/blog/[slug]/page.module.css b/app/blog/[slug]/page.module.css
index 31557fd..dd798f7 100644
--- a/app/blog/[slug]/page.module.css
+++ b/app/blog/[slug]/page.module.css
@@ -1,5 +1,9 @@
.subtitle {
- font-size: 0.83255rem;
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+ font-size: 0.78rem;
+ letter-spacing: 0.01em;
+ color: var(--color-terminal-dim);
line-height: 1.75rem;
display: block;
margin-bottom: 1.75rem;
diff --git a/app/globals.css b/app/globals.css
index f65f1e7..96a0dc5 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -7,7 +7,15 @@
--color-inline-code-text: #e6e6e6;
--color-shadow: rgba(140, 160, 227, 0.6);
--color-text-body: rgba(255, 255, 255, 0.88);
- --font-mono: Consolas, Menlo, Monaco, source-code-pro, Courier New, monospace;
+
+ /* Retro terminal accents (reuse the existing palette) */
+ --color-terminal: var(--color-accent);
+ --color-terminal-dim: rgba(255, 255, 255, 0.5);
+
+ --font-mono:
+ var(--font-mono-display), 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo,
+ Consolas, Monaco, 'Courier New', monospace;
+ --font-display: var(--font-mono);
}
html {
@@ -363,10 +371,11 @@ h4,
h5,
h6 {
margin-top: 3rem;
- font-family: var(--font-montserrat);
+ font-family: var(--font-display);
color: inherit;
text-rendering: optimizeLegibility;
- font-weight: 300;
+ font-weight: 400;
+ letter-spacing: -0.01em;
}
hr:has(+ h1),
hr:has(+ h2),
@@ -379,7 +388,7 @@ hr:has(+ h6) {
h1 {
margin-bottom: 1.75rem;
- font-family: var(--font-montserrat);
+ font-family: var(--font-display);
font-size: 2rem;
line-height: 1.2;
}
diff --git a/app/layout.tsx b/app/layout.tsx
index ef320e3..78def14 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,4 +1,4 @@
-import { Montserrat, Plus_Jakarta_Sans } from 'next/font/google'
+import { IBM_Plex_Mono, Plus_Jakarta_Sans } from 'next/font/google'
import Script from 'next/script'
import { Suspense } from 'react'
@@ -19,10 +19,11 @@ const jakarta = Plus_Jakarta_Sans({
display: 'swap',
})
-const montserrat = Montserrat({
+const plexMono = IBM_Plex_Mono({
subsets: ['latin'],
- weight: ['300'],
- variable: '--font-montserrat',
+ weight: ['300', '400', '500', '600'],
+ style: ['normal', 'italic'],
+ variable: '--font-mono-display',
display: 'swap',
})
@@ -30,7 +31,7 @@ export const metadata = getBaseMetadata()
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
-
+
diff --git a/app/page.module.css b/app/page.module.css
index c162367..71262b5 100644
--- a/app/page.module.css
+++ b/app/page.module.css
@@ -1,7 +1,10 @@
.label {
display: block;
- font-size: 0.85rem; /* Match subtitle */
- color: var(--color-accent);
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+ font-size: 0.78rem;
+ letter-spacing: 0.08em;
+ color: var(--color-terminal);
margin-bottom: 1rem;
opacity: 0.85;
}
diff --git a/app/stream/page.module.css b/app/stream/page.module.css
index 1a539fa..a55b4a2 100644
--- a/app/stream/page.module.css
+++ b/app/stream/page.module.css
@@ -34,8 +34,10 @@
}
.date {
- font-size: 0.8rem;
- color: rgba(255, 255, 255, 0.5);
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+ font-size: 0.72rem;
+ color: var(--color-terminal-dim);
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
@@ -46,7 +48,9 @@
}
.tag {
- font-size: 0.65rem;
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+ font-size: 0.62rem;
color: rgba(255, 255, 255, 0.4);
text-transform: uppercase;
letter-spacing: 0.05em;
@@ -68,4 +72,3 @@
font-size: 0.7rem;
}
}
-
diff --git a/components/FeedItem.module.css b/components/FeedItem.module.css
index 85945c5..ca61520 100644
--- a/components/FeedItem.module.css
+++ b/components/FeedItem.module.css
@@ -43,7 +43,12 @@
}
.subtitle {
- opacity: 0.85;
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+ font-size: 0.74rem;
+ letter-spacing: 0.01em;
+ color: var(--color-terminal-dim);
+ opacity: 0.95;
}
.description {
diff --git a/components/Footer.module.css b/components/Footer.module.css
index ab7810f..ed7cfe7 100644
--- a/components/Footer.module.css
+++ b/components/Footer.module.css
@@ -7,7 +7,7 @@
}
.footerInner {
- padding: 30px;
+ padding: 30px 30px 12px;
font-size: 10px;
display: flex;
align-items: center;
@@ -15,6 +15,21 @@
gap: 20px;
}
+.signature {
+ padding: 0 30px 30px;
+ text-align: center;
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+ font-size: 0.72rem;
+ letter-spacing: 0.02em;
+ color: var(--color-terminal-dim);
+}
+
+.prompt {
+ color: var(--color-accent);
+ margin-right: 0.25em;
+}
+
.svgIcon {
height: 30px;
fill: #aaa;
diff --git a/components/Footer.tsx b/components/Footer.tsx
index 3a29d5e..7fb01a2 100644
--- a/components/Footer.tsx
+++ b/components/Footer.tsx
@@ -76,6 +76,10 @@ export function Footer() {
+
+
+ $ by Kenneth Skovhus
+
)
}
diff --git a/components/Header.module.css b/components/Header.module.css
index cd9c3cf..47e263c 100644
--- a/components/Header.module.css
+++ b/components/Header.module.css
@@ -27,40 +27,69 @@
color: white;
display: flex;
align-items: center;
+ gap: 12px;
height: 60px;
+ font-family: var(--font-mono);
+ font-variant-ligatures: none;
+}
+
+/* Terminal prompt: skovhus$ */
+
+.prompt {
+ display: inline-flex;
+ align-items: baseline;
+ font-size: 15px;
+ letter-spacing: -0.01em;
+ text-decoration: none;
+ white-space: nowrap;
+ flex-shrink: 0;
+ opacity: 0.95;
+ transition: opacity 0.2s ease;
+}
+
+.prompt:hover {
+ opacity: 1;
+}
+
+.promptUser {
+ color: var(--color-terminal);
+}
+
+.promptSign {
+ color: rgba(255, 255, 255, 0.9);
}
.navLinkContainer {
display: flex;
- gap: 10px;
+ gap: 6px;
align-items: center;
}
.navLink {
- font-size: 16px;
+ font-size: 15px;
opacity: 0.5;
text-decoration: none;
- transition: opacity 0.2s ease;
-}
-
-.navLinkActive {
- opacity: 0.9;
+ padding: 2px 6px;
+ border-radius: 2px;
+ transition:
+ opacity 0.2s ease,
+ background-color 0.2s ease,
+ color 0.2s ease;
}
.navLink:hover {
opacity: 1;
}
-.siteName {
- letter-spacing: 0.02em;
-}
-
-.siteName:hover {
- opacity: 1 !important;
+/* Active link rendered as a selected DOS-style menu cell */
+.navLinkActive {
+ opacity: 1;
+ color: var(--background-context-color);
+ background-color: var(--color-terminal);
}
-.showOnMobile {
- display: none;
+.navLinkActive:hover {
+ color: var(--background-context-color);
}
/* Mobile breakpoint: 500px - keep in sync with globals.css */
@@ -69,11 +98,24 @@
position: relative;
}
- .hideOnMobile {
- display: none;
+ .nav {
+ gap: 6px;
}
- .showOnMobile {
- display: inline;
+ .prompt {
+ font-size: 14px;
+ }
+
+ .navLinkContainer {
+ gap: 3px;
+ }
+
+ .navLink {
+ font-size: 14px;
+ padding: 2px 4px;
+ }
+
+ .hideOnMobile {
+ display: none;
}
}
diff --git a/components/Header.tsx b/components/Header.tsx
index c7029bc..c6aabf2 100644
--- a/components/Header.tsx
+++ b/components/Header.tsx
@@ -3,8 +3,6 @@ import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { type MouseEvent, useEffect, useState } from 'react'
-import { getSlideAnimationProps } from '#/lib/slide-animation'
-
import styles from './Header.module.css'
const pages = [
@@ -17,7 +15,6 @@ const pages = [
export function Header() {
const pathname = usePathname()
- const slideAnimation = getSlideAnimationProps({ stage: 0 })
const [scrollY, setScrollY] = useState(0)
useEffect(() => {
@@ -41,14 +38,21 @@ export function Header() {
}
const isScrolled = scrollY > 10
- const nameOpacity = Math.max(0.5, 1 - scrollY / 160)
return (
-
)