diff --git a/README.md b/README.md
index b86db0b..919ccff 100644
--- a/README.md
+++ b/README.md
@@ -2,16 +2,18 @@
> The source code for my personal website, **[dvorakmortonxd.dev](https://dvorakmortonxd.dev)**.
-It's an **editorial-style personal site** in a **gruvbox** palette, with the whole KDE
-desktop simulation kept behind a "Desktop mode" button. Two modes, one content set:
+It's a **skeuomorphic personal site**: a dark homelab desk built from anodised aluminium, OLED
+glass, carbon fibre and paper, with the whole KDE desktop simulation kept behind a physical
+power switch. Two modes, one content set:
-- **Web** (default) — the editorial site: a technical-print layout painted in the gruvbox
- palette, with serif headlines, mono labels in the margin, hairline rules and a data strip. No
- images at all; the only graphics are the social icons, used as monochrome CSS masks.
+- **Web** (default) — the homelab desk. A 4U rack carries the headline on an engraved nameplate
+ and a live console readout; services are rack units with status LEDs, the 18 coding projects
+ are labelled SSD caddies in a drive drawer, hardware hangs on a pegboard, the contribution
+ heatmap is an LED matrix and the socials are a patch panel. Textures are CC0 — see
+ [`/credits`](http://localhost:3000/credits).
- **Desktop mode** — the KDE Plasma / Windows-style **desktop simulation**: draggable
snap-to-grid icons, resizable/floating windows, a Start menu, taskbar, live clock and a
- working in-browser terminal (Alacritty). Reachable from the "Desktop mode" button and hidden
- on phones.
+ working in-browser terminal (Alacritty). Reached from the power switch and hidden on phones.
Both modes surface the same personal content: socials, self-hosted services with **live
up/down health checks**, a hardware collection, coding projects, a **GitDXD contribution
@@ -19,13 +21,13 @@ heatmap**, gym SBD and links to friends' sites.
## ✨ Features
-- **Web theme is the landing view** — the site always opens on the editorial page; the theme is
- deliberately not persisted, so a reload never drops you into the desktop. A technical-print
- layout with serif headlines, mono labels in the margin, hairline rules and a data strip. Text
- and type only — the sole graphics are the social icons, rendered as monochrome CSS masks.
-- **Desktop mode (desktop-only)** — a "Desktop mode" button swaps to the KDE-style desktop for
- the session. Phones never get it: the buttons are hidden, so the old iOS-style phone home
- screen is gone.
+- **Web theme is the landing view** — the site always opens on the desk; the theme is
+ deliberately not persisted, so a reload never drops you into the desktop.
+- **Skeuomorphic hardware** — rack, LEDs, rocker switch, screws, vents and panels are CSS
+ materials over five CC0 textures; every section is a real-world object rather than a card.
+- **Desktop mode (desktop-only)** — a physical power switch in the top rail (and in the footer)
+ flips to the KDE-style desktop for the session. Phones never get it: the switch is hidden, so
+ the old iOS-style phone home screen is gone.
- **Draggable desktop icons** — free placement that snaps to a measured grid, one icon per
cell, with a follow-the-cursor drag ghost. Icons shrink on cramped viewports so they never
collide.
@@ -61,15 +63,16 @@ heatmap**, gym SBD and links to friends' sites.
- **Framework:** Next.js 16 (App Router, Turbopack)
- **Language:** TypeScript, React 19 (client components everywhere interactivity lives)
-- **Styling:** `src/app/globals.css` is the web editorial design system — the gruvbox palette as
- CSS custom properties, plus Tailwind v4 `@theme`/`@utility`, base and scroll reveals.
- `editorial.css` holds page helpers; `page.css` keeps the shared component styles the desktop
- apps still use, and `skeuo.css` is the KDE desktop. The editorial page is built from Tailwind
- utilities.
-- **Fonts:** Newsreader (display) + IBM Plex Sans/Mono (body/labels) via `next/font/google`;
- the desktop keeps its system sans stack.
-- **Images:** `next/image` — but the editorial page uses none (social SVGs as monochrome masks only).
-- **Version:** `3.0.0` (see `package.json`)
+- **Styling:** `src/app/globals.css` holds the palette tokens, base styles, the Tailwind v4
+ `@theme`/`@utility` classes and the scroll reveals. `src/app/web.css` is the skeuomorphic
+ material system (metal, OLED glass, paper, carbon, rubber, plastic, LEDs, screws, vents,
+ switches) and the object layouts. `page.css` keeps the shared component styles the desktop
+ apps still use, and `skeuo.css` is the KDE desktop.
+- **Fonts:** Newsreader (headlines, paper) + IBM Plex Sans/Mono (body, machine labels) via
+ `next/font/google`; the desktop keeps its system sans stack.
+- **Textures:** five CC0 materials from ambientCG, downscaled to 512 px in `public/textures`.
+ Attribution is on `/credits`.
+- **Version:** `3.1.0` (see `package.json`)
## 🚀 Running Locally
@@ -171,11 +174,12 @@ they contend for `:3000` and `.next/dev/lock`.
src/app/
page.tsx → renders , imports the theme stylesheets
layout.tsx → html shell + metadata; loads the fonts; injects ThemeScript
- globals.css → web editorial design system (gruvbox palette; tokens, @utility classes, base)
- editorial.css → editorial page helpers (social masks, heatmap)
+ globals.css → palette tokens, base, Tailwind @theme/@utility, scroll reveals
+ web.css → skeuomorphic material system + object layouts
page.css → shared component styles still used by the desktop apps
skeuo.css → KDE desktop styles
data.ts → socials, codingProjects, techProjects, friends, wallpapers
+ credits/page.tsx → credit page for the textures and fonts
revival-inc/page.tsx → embeds the bundled game at /public/revival-inc/index.html
api/
heatmap/route.ts → contribution heatmap proxy
@@ -183,11 +187,11 @@ src/app/
frame/route.ts → header-stripping proxy for unframeable friend sites
ping/route.ts → service health check (HTTP + Minecraft)
components/
- ThemeRoot.tsx → web editorial vs. Desktop mode
+ ThemeRoot.tsx → web desk vs. Desktop mode
ThemeScript.tsx → pre-paint script: device detection
useTheme.ts → theme state via useSyncExternalStore
- EditorialSite.tsx → the web editorial page (nav, hero, sections)
- editorial-ui.tsx → editorial primitives: Section, ServiceRow, Contributions, …
+ WebSite.tsx → the desk: rack hero, drawer, pegboard, patch panel
+ web-ui.tsx → rack units, LED dashboard, social masks, Reveal
WindowsDesktop.tsx → desktop shell: icons, windows, taskbar, Start menu
WinWindow.tsx → one draggable/resizable window
apps.tsx → APPS registry, window contents, in-app terminal
diff --git a/agents.md b/agents.md
index a1a8a00..2024e64 100644
--- a/agents.md
+++ b/agents.md
@@ -34,17 +34,19 @@ When in doubt, prefer updating. A stale README **or** agents.md is treated as a
## What this project is
Personal portfolio site for **dvorakmortonxd.dev**. The default view is a
-**web editorial page** (a technical-print layout, no images); a "Desktop mode"
-button swaps to a **KDE Plasma desktop simulation**. Phones only ever get the
-editorial page.
+**skeuomorphic homelab desk** (a rack, LEDs, paper, anodised metal); a physical
+power switch flips to a **KDE Plasma desktop simulation**. Phones only ever get
+the desk.
- Framework: **Next.js 16** (App Router, Turbopack), **React 19**, TypeScript.
-- Styling: **Tailwind v4** for the editorial page — `globals.css` is the design
- system (CSS custom properties, `@theme` tokens, `@utility` classes) — plus plain
- CSS for the desktop (`skeuo.css`) and the shared component styles the desktop
- apps still use (`page.css`).
+- Styling: **Tailwind v4** for layout plus **`web.css`**, the skeuomorphic
+ material system (metal, OLED glass, paper, carbon, rubber, plastic, LEDs,
+ screws, vents, switches) over five CC0 textures in `public/textures`
+ (credited on `/credits`). `globals.css` holds the tokens, base styles and the
+ reveals; `skeuo.css` and `page.css` are the desktop and the shared
+ desktop-app styles.
- Path alias: `@/*` → `src/*`.
-- Version: `3.0.0` (see `package.json`).
+- Version: `3.1.0` (see `package.json`).
### Scripts
```bash
@@ -77,11 +79,12 @@ token.** Do not print it, copy it into new files, or push it anywhere else.
src/app/
page.tsx → renders , imports the theme stylesheets
layout.tsx → html shell, metadata, next/font, ThemeScript
- globals.css → web editorial design system (gruvbox palette; tokens, @utility, base, reveals)
- editorial.css → editorial page helpers (social masks, heatmap)
+ globals.css → palette tokens, base, @theme/@utility, scroll reveals
+ web.css → skeuomorphic material system + object layouts
page.css → shared component styles used by the desktop apps
skeuo.css → KDE Plasma desktop styles
data.ts → socials, codingProjects, techProjects, friends, wallpapers
+ credits/page.tsx → credits for the CC0 textures and fonts
revival-inc/page.tsx → fullscreen iframe embedding /public/revival-inc/index.html
api/
heatmap/route.ts → proxy for git.dvorakmortonxd.dev contribution heatmap
@@ -89,9 +92,9 @@ src/app/
ping/route.ts → service health check (HTTP + minecraft:// via mcstatus.io); host allowlist
frame/route.ts → header-stripping proxy so an unframeable friend site loads in a window; host allowlist
components/
- ThemeRoot.tsx → editorial page by default, desktop when theme === "skeuo"
- EditorialSite.tsx → the web editorial page (nav, hero, sections)
- editorial-ui.tsx → editorial primitives: Reveal, Section, ServiceRow, Contributions, …
+ ThemeRoot.tsx → the web desk by default, desktop when theme === "skeuo"
+ WebSite.tsx → the desk: rack hero, drive drawer, pegboard, patch panel
+ web-ui.tsx → rack units, LED dashboard, social masks, Reveal
WindowsDesktop.tsx → "skeuo" theme, desktop: icons, windows, taskbar
WinWindow.tsx → a single draggable/resizable window
apps.tsx → APPS registry + the content of each app + in-app terminal
@@ -115,17 +118,19 @@ scripts/
2. `useTheme()` (in `useTheme.ts`) reads `data-theme` via `useSyncExternalStore`;
`setTheme` sets the attribute and dispatches `theme-change`. Nothing is
persisted, so a reload returns to `web`.
-3. `ThemeRoot` renders `EditorialSite` unless `theme === "skeuo"`, in which case it
- mounts `WindowsDesktop` instead. The editorial page stays mounted (hidden) while
- the desktop is up so its scroll position survives; the desktop mounts on demand
+3. `ThemeRoot` renders `WebSite` unless `theme === "skeuo"`, in which case it
+ mounts `WindowsDesktop` instead. The desk stays mounted (hidden) while the
+ desktop is up so its scroll position survives; the desktop mounts on demand
(phones can never reach `skeuo`).
-Modes: `web` = the editorial site (default/landing), `skeuo` = KDE Plasma desktop.
+Modes: `web` = the skeuomorphic homelab desk (default/landing), `skeuo` = KDE
+Plasma desktop.
-The editorial page is **asset-free** apart from the social SVGs, which are used as
-monochrome CSS masks (`.social-mask` in `editorial.css`). `linkedin.svg` is a filled
-badge that masks to a plain square, so `editorial-ui.tsx` renders an inline mark for
-it instead. The desktop still uses the image assets.
+The desk uses **five CC0 textures** from ambientCG (`public/textures`: metal,
+paper, carbon, rubber, plastic), downscaled to 512 px and credited on
+`/credits`. The social SVGs are used as monochrome CSS masks (`.social-mask`);
+`linkedin.svg` is a filled badge that masks to a plain square, so `web-ui.tsx`
+renders an inline mark for it instead. The desktop still uses the image assets.
---
@@ -225,14 +230,18 @@ not free placement. Don't confuse the two.
- Components are client components (`"use client"` at the top) — they use
pointer events and window APIs freely.
- CSS classes are prefixed by area: `win-` (desktop), `app-` / `kickoff` etc.
- (desktop windows), plus the editorial design-system classes (`shell`, `display`,
- `label`, `rule*`, `glass*`). Grep by prefix to find styles.
-- The editorial page reveals blocks with `.reveal` (see `Reveal` in
- `editorial-ui.tsx`): hidden by default, `.is-in` shows. On load the first
- screenful cascades top-to-bottom (90ms per block, in DOM order); the rest
- reveal when they scroll in. **Wrap every content block** — anything left
- unwrapped paints before the top and breaks the top-to-bottom order. The
- `