revert "turn the terminal/Gruvbox theme into the skeuo console" (d3f953e)

Back to the terminal/Gruvbox shell + phone-reachable KDE desktop. The reverted
work is still reachable in history at d3f953e.
This commit is contained in:
Martin Dvořák 2026-09-30 10:48:22 +00:00
commit 32d622f80e
17 changed files with 2837 additions and 4442 deletions

View file

@ -8,7 +8,7 @@ import { NextResponse } from 'next/server';
//
// Host matching is exact or by subdomain (e.g. anything under
// dvorakmortonxd.dev). Keep this in sync with the ServiceButton `url`/`checkUrl`
// values in components/apps.tsx and components/SkeuoLayout.tsx, and with the
// values in components/apps.tsx and components/TerminalLayout.tsx, and with the
// friend list in data.ts.
const ALLOWED_HOSTS = [
'dvorakmortonxd.dev', // ai / jelly / navidrome / git / proxmox / mc (SMP)

View file

@ -1,519 +0,0 @@
"use client";
import Image from "next/image";
import type { CSSProperties, ReactNode } from "react";
import JokerLogo from "./JokerLogo";
import ServiceButton from "./ServiceButton";
import ContributionHeatmap from "./ContributionHeatmap";
import { setTheme } from "./useTheme";
import { socials, codingProjects, techProjects, friends } from "../data";
/* ------------------------------------------------------------------ parts */
/** A small engraved brass / enamel plate — every object is labelled like a machine. */
function Plate({
children,
tone = "brass",
className = "",
}: {
children: ReactNode;
tone?: "brass" | "red" | "ivory";
className?: string;
}) {
return <span className={`sk-tag sk-tag--${tone} ${className}`}>{children}</span>;
}
/** A recessed dark-glass window: where the console prints machine output. */
function Readout({ children, className = "" }: { children: ReactNode; className?: string }) {
return (
<div className={`sk-readout ${className}`}>
<span className="sk-readout__glare" aria-hidden="true" />
<span className="sk-readout__text">{children}</span>
</div>
);
}
/** Weight → needle angle on a 240° dial. */
const GAUGE_MAX = 180;
const needle = (kg: number) => `${(-120 + (kg / GAUGE_MAX) * 240).toFixed(1)}deg`;
const GYM = [
{ key: "squat", label: "SQUAT", weight: 125, date: "5.1.2025", icon: "/squat.svg" },
{ key: "bench", label: "BENCH", weight: 111, date: "29.5.2026", icon: "/bench.svg" },
{ key: "deadlift", label: "DEADLIFT", weight: 165, date: "17.12.2024", icon: "/deadlift.svg" },
];
/* ------------------------------------------------------------------- page */
export default function SkeuoLayout() {
return (
<div className="sk-world">
<div className="sk-console">
{/* ------------------------------------------------------ nameplate */}
<header className="sk-nameplate">
<span className="sk-bezel sk-bezel--logo">
<JokerLogo />
</span>
<h1 className="sk-nameplate__name">dvorakmortonxd.dev</h1>
<span className="sk-nameplate__deco" aria-hidden="true">
<span className="sk-nameplate__vent" />
<span className="sk-nameplate__lamps">
<i className="sk-lamp sk-lamp--amber sk-lamp--blink" />
<i className="sk-lamp sk-lamp--green" />
</span>
</span>
<button
type="button"
className="sk-switch sk-desktop-switch"
onClick={() => setTheme("desktop")}
title="Boot the desktop simulation"
>
<span className="sk-switch__label">DESKTOP</span>
<span className="sk-switch__track" aria-hidden="true">
<span className="sk-switch__knob" />
</span>
<span className="sk-lamp sk-lamp--amber" aria-hidden="true" />
</button>
</header>
<main className="sk-stack">
{/* ------------------------------------------------------ welcome */}
<section className="sk-panel sk-panel--welcome">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate className="sk-panel__plate">README.MD</Plate>
<div className="sk-welcome__body">
<Readout className="sk-welcome__prompt">
<span className="sk-readout__ok">martin@dvorakmortonxd</span>
<span className="sk-readout__dim">:~$</span> whoami
<span className="sk-caret" aria-hidden="true" />
</Readout>
<p className="sk-emboss sk-welcome__copy">
Welcome my personal website! Here I show off my projects and hardware I own,
aswell as my self-hosted services :)
</p>
</div>
<span className="sk-lamp sk-lamp--amber sk-lamp--blink sk-welcome__lamp" aria-hidden="true" />
</section>
{/* ------------------------------------------------------ socials */}
<section className="sk-panel sk-panel--socials">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate className="sk-panel__plate">SOCIALS.JS</Plate>
<p className="sk-caption">Patch bay — every line is a live feed</p>
<div className="social-buttons sk-patchbay">
{socials.map((s) => (
<a
key={s.name}
href={s.url}
target="_blank"
rel="noopener noreferrer"
className="social-button"
>
<Image src={s.icon} alt={s.name} width={16} height={16} className="social-icon" />
<span className="social-label">{s.name}</span>
</a>
))}
</div>
<p className="mail-contact sk-mail">
<span className="sk-mail__tape" aria-hidden="true" />
mail if u ever wanna contact me:{" "}
<a href="mailto:dvorak@dvorakmortonxd.dev">dvorak@dvorakmortonxd.dev</a>
</p>
</section>
{/* ---------------------------------------------------------- gym */}
<section className="sk-panel sk-panel--gym">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate tone="ivory" className="sk-panel__plate">
GYM_SBD_AT_73KG_BW.DB
</Plate>
<p className="sk-caption">Analogue load meters — best lifts, bodyweight 73 kg</p>
<div className="gym-grid">
{GYM.map((g) => (
<div key={g.key} className="gym-item">
<div className="sk-gauge" style={{ "--needle": needle(g.weight) } as CSSProperties}>
<span className="sk-gauge__face">
<span className="sk-gauge__ticks" aria-hidden="true" />
<span className="sk-gauge__needle" aria-hidden="true" />
<span className="sk-gauge__hub" aria-hidden="true" />
<Image src={g.icon} alt={g.label} width={48} height={48} className="gym-icon" />
</span>
<span className="sk-gauge__glass" aria-hidden="true" />
</div>
<div className="gym-label">{g.label}</div>
<div className="gym-weight">
<span className="sk-num">{g.weight}</span>kg
</div>
<div className="gym-date">{g.date}</div>
</div>
))}
</div>
</section>
{/* ---------------------------------------------------------- now */}
<section className="sk-panel sk-panel--now">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate tone="ivory" className="sk-panel__plate">
NOW.TXT
</Plate>
<div className="sk-clipboard">
<span className="sk-clipboard__clip" aria-hidden="true" />
<span className="sk-clipboard__board" aria-hidden="true" />
<div className="sk-sheet sk-sheet--note">
<span className="sk-sheet__tab" aria-hidden="true">
<span className="sk-sheet__hole" />
NOW
</span>
<Readout className="sk-inline-readout">
<span className="sk-readout__ok">martin@dvorakmortonxd</span>
<span className="sk-readout__dim">:~$</span> cat now.txt
</Readout>
<p className="sk-type">
I&#39;m currently hosting an SMP (dm me on discord). Also I&#39;m pretty much cooking
daily, because im bulking through out the non-summer seasons. And me and my pal{" "}
<a href="https://skopec.dev">Pepa</a> are working on an education app so we can study
more efficiently, It&#39;s called{" "}
<a href="https://git.dvorakmortonxd.dev/edu/maturita.c">maturita.c</a>!
</p>
<span className="sk-caret sk-caret--on-paper" aria-hidden="true" />
</div>
</div>
</section>
{/* -------------------------------------------------- about me */}
<section className="sk-ledger">
<span className="sk-ledger__stitch" aria-hidden="true" />
<Plate className="sk-ledger__plate">README.MD</Plate>
<span className="sk-ledger__corner" aria-hidden="true" />
<div className="sk-sheet sk-sheet--page">
<Readout className="sk-inline-readout">
<span className="sk-readout__ok">martin@dvorakmortonxd</span>
<span className="sk-readout__dim">:~$</span> cat about_me.md
</Readout>
<p className="sk-type">
Hey, I&#39;m Martin Dvořák — a 17(soon to be 18)-year-old IT student based in the Czech
Republic, specializing in network management and administration at{" "}
<a href="https://sssvt.cz">sssvt.cz</a>. I&#39;m a sophomore and I have wanted to go to
this school since 7th grade (2022) so I&#39;m happy I got in in 2025, the school is pretty
cool so if you are in middle school and interested in IT, make sure to check it out.
I&#39;m a homelabber and developer heavily focused on self-hosting <i>literally everything</i>,
writing code (for example games for gamejams), tinkering with GNU/Linux or Musl/Linux
systems and retro hardware. I own a small collection of laptops ranging from 2009 to 2014
(and ofcourse my 2025 macbook), most of these found in ewaste. In my free time I mostly
spend time with my gf {"<"}3, I also spend a bit of time setting up my self hosted stuff
(like jellyfin or gitdxd), and also when I&#39;m in my gaming mood I play terraria (around
1300hr playtime btw) and minecraft modpacks with mekanism and/or create. I also go to the
gym around 3-5 times a week, running a PPL split focused on strength/powerlifting and
especially SBD. I take a big focus on my health and physique.
<span className="sk-caret sk-caret--on-paper" aria-hidden="true" />
</p>
</div>
</section>
{/* ----------------------------------------------------- services */}
<section className="sk-rack">
<div className="sk-rack__head">
<Plate className="sk-rack__plate">SERVICES.HTML</Plate>
<span className="sk-lamp sk-lamp--green sk-lamp--blink" aria-hidden="true" />
<span className="sk-rack__hint">health checked from this page</span>
</div>
<div className="services-buttons services-main sk-rack__rail">
<ServiceButton
url="https://proxmox.dvorakmortonxd.dev/"
className="proxmox sk-module"
icon="🖥️"
name="Proxmox"
desc="Server Management"
access="private"
disabled
/>
<ServiceButton
url="https://ai.dvorakmortonxd.dev/"
className="ai sk-module"
icon="🦾"
name="Llama.cpp"
desc="Local AI Server"
access="on_request"
/>
<ServiceButton
url="https://jelly.dvorakmortonxd.dev/"
className="jellyfin sk-module"
icon="🎬"
name="Jellyfin"
desc="Local Media Server"
access="on_request"
/>
<ServiceButton
url="https://discord.gg/vyvhk7d8bX"
checkUrl="minecraft://mc.dvorakmortonxd.dev:25565"
className="pterodactyl sk-module"
icon="🎮"
name="SMP"
desc="My Survival Minecraft Server"
access="on_request"
/>
<ServiceButton
url="https://navidrome.dvorakmortonxd.dev/"
className="funkwhale sk-module"
icon="🎸"
name="Navidrome"
desc="Music Streaming"
access="private"
/>
<ServiceButton
url="https://git.dvorakmortonxd.dev"
className="gitdxd sk-module"
icon="🐙"
name="GitDXD"
desc="Best Git Hosting OAT"
access="public"
/>
</div>
</section>
{/* ------------------------------------------------------- gitdxd */}
<section className="sk-panel sk-panel--feature">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate className="sk-panel__plate">GITDXD.GIT</Plate>
<div className="sk-feature">
<h2 className="sk-engrave sk-feature__title">GitDXD</h2>
<p className="sk-emboss sk-feature__sub">My Self-hosted Git Instance</p>
<figure className="sk-frame">
<span className="sk-frame__glass" aria-hidden="true" />
<Image src="/gitdxd.webp" alt="GitDXD Preview" width={1280} height={720} className="sk-frame__img" />
<figcaption className="sk-frame__caption">forgejo · git.dvorakmortonxd.dev</figcaption>
</figure>
<div className="sk-sheet sk-sheet--strip">
<p className="sk-type">
My very own forgejo git instance, originally started as a private git instance for me
and my friends to boycott GitHub but I&#39;ve made it public now so. Join at{" "}
<a href="https://git.dvorakmortonxd.dev">git.dvorakmortonxd.dev</a>.
<span className="sk-caret sk-caret--on-paper" aria-hidden="true" />
</p>
</div>
</div>
</section>
{/* ------------------------------------------------ contributions */}
<section className="sk-recorder">
<div className="sk-recorder__head">
<Plate tone="ivory" className="sk-recorder__plate">
CONTRIBUTIONS@GITDXD.GIT
</Plate>
<span className="sk-recorder__roller" aria-hidden="true" />
</div>
<div className="sk-recorder__paper">
<ContributionHeatmap />
</div>
</section>
{/* ----------------------------------------------------- revival */}
<section className="sk-panel sk-panel--feature">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate tone="ivory" className="sk-panel__plate">
REVIVAL.INC
</Plate>
<div className="sk-feature sk-feature--cart">
<div className="sk-cart">
<span className="sk-cart__ridge" aria-hidden="true" />
<Image
src="/revivalinc.webp"
alt="revival inc thumbnail"
width={768}
height={576}
className="sk-cart__art"
/>
<span className="sk-cart__rib" aria-hidden="true" />
<h2 className="sk-cart__title">Revival inc.</h2>
<span className="sk-screw sk-cart__screw" aria-hidden="true" />
</div>
<div className="sk-sheet sk-sheet--strip">
<p className="sk-engrave sk-feature__sub">What is it?</p>
<p className="sk-type">
It&#39;s a game I made for the game jam &#34;Mini Jame Gam #55&#34;, the theme was
Necromancy and the special item was Milk, the game also includes a tutorial so if you
wanna try it do it. Check it out at{" "}
<a href="https://martin-dv.itch.io/revival-inc">itch.io</a> or play{" "}
<a href="https://dvorakmortonxd.dev/revival-inc">here</a>.
<span className="sk-caret sk-caret--on-paper" aria-hidden="true" />
</p>
</div>
</div>
</section>
{/* --------------------------------------------------- rustywolf */}
<section className="sk-panel sk-panel--feature">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate className="sk-panel__plate">RUSTYWOLF.RS</Plate>
<div className="sk-feature sk-feature--box">
<div className="sk-box">
<span className="sk-box__spine" aria-hidden="true">
RUSTYWOLF
</span>
<Image
src="/RustyWolfPreview.webp"
alt="RustyWolf Browser Preview"
width={1280}
height={720}
className="sk-box__art"
/>
<span className="sk-box__edge" aria-hidden="true" />
</div>
<div className="sk-sheet sk-sheet--strip">
<p className="sk-engrave sk-feature__sub">Introducing RustyWolf — what makes it so cool???</p>
<p className="sk-type">
A lightweight browser made in Rust with WebKitGTK. It&#39;s the successor to my previous
project Venturesome, aiming to provide a fast and minimalist browsing experience.
It&#39;s a perfect browser for old machines that struggle with modern browsers. Check it
out at{" "}
<a href="https://git.dvorakmortonxd.dev/dvorakmortonxd/RustyWolf">GitDXD</a>.
<span className="sk-caret sk-caret--on-paper" aria-hidden="true" />
</p>
</div>
</div>
</section>
{/* ----------------------------------------------------- hardware */}
<section className="sk-board">
<div className="sk-board__head">
<Plate className="sk-board__plate">TECH_LIST.JSON</Plate>
<h2 className="sk-paint sk-section-title">All my hardware equipment :)</h2>
</div>
<div className="sk-board__face">
<div className="project-grid sk-board__tags">
{techProjects.map((project) => (
<div key={project.title} className="project-card sk-tagcard">
<span className="sk-tagcard__hook" aria-hidden="true" />
<span className="sk-tagcard__eyelet" aria-hidden="true" />
<div
className="project-image sk-tagcard__photo"
style={{ backgroundImage: `url(${project.image})` }}
>
<span className="sk-tagcard__clip" aria-hidden="true" />
</div>
<h4 className="project-title">{project.title}</h4>
<p className="project-desc">{project.desc}</p>
</div>
))}
</div>
</div>
</section>
{/* ----------------------------------------------------- projects */}
<section className="sk-drawer">
<div className="sk-drawer__head">
<Plate tone="ivory" className="sk-drawer__plate">
PROJECTS.DOCX
</Plate>
<h2 className="sk-paint sk-section-title">All the stuff I&#39;ve worked on :))</h2>
</div>
<div className="sk-drawer__body">
<div className="sk-drawer__inner">
<div className="project-grid sk-drawer__cards">
{codingProjects.map((project, idx) => (
<a
key={idx}
href={project.url}
target="_blank"
rel="noopener noreferrer"
className="project-card sk-indexcard"
>
<div className="sk-indexcard__tab" aria-hidden="true" />
<div
className="project-image sk-indexcard__photo"
style={{ backgroundImage: `url(${project.img})` }}
/>
<h4 className="project-title">{project.title}</h4>
<p className="project-desc">{project.desc}</p>
</a>
))}
</div>
</div>
<div className="sk-drawer__front">
<span className="sk-drawer__pull" aria-hidden="true" />
</div>
</div>
</section>
{/* ------------------------------------------------------ friends */}
<section className="sk-panel sk-panel--friends">
<span className="sk-panel__screws" aria-hidden="true">
<i className="sk-screw" />
<i className="sk-screw" />
</span>
<Plate className="sk-panel__plate">FRIENDS.TSX</Plate>
<h2 className="sk-paint sk-section-title sk-section-title--center">
Friend&#39;s websites and projects
</h2>
<div className="services-buttons sk-callcards">
{friends.map((friend, idx) => (
<ServiceButton
key={idx}
url={friend.realUrl || friend.url}
className="friend sk-callcard"
icon={<Image src={friend.img} alt={friend.name} width={68} height={68} className="friend-icon" />}
name={friend.name}
desc={friend.desc}
/>
))}
</div>
</section>
</main>
{/* -------------------------------------------------------- footer */}
<footer className="sk-baseplate">
<span className="sk-baseplate__screw sk-baseplate__screw--l" aria-hidden="true" />
<span className="sk-baseplate__screw sk-baseplate__screw--r" aria-hidden="true" />
<span className="sk-baseplate__version">v2.1.0</span>
<p className="sk-baseplate__legal">
© 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just follow the
GPL3.0 License)
</p>
</footer>
</div>
</div>
);
}

View file

@ -0,0 +1,106 @@
"use client";
import { useEffect, useState } from "react";
const TRAIN_ASCII = ` ==== ________ ___________
_D _| |_______/ \\__I_I_____===__|_________|
|(_)--- | H\\________/ | | =|___ ___| _________________ _________________ _________________ _________________ _________________ _________________
/ | | H | | | | ||_| |_|| _| \\_____| \\_____| \\_____| \\_____| \\_____| \\_____A
| | | H |__--------------------| [___] | =| | | | | | |
| ________|___H__/__|_____/[][]~\\_______| | -| | | | | | |
|/ | |-----------I_____I [][] [] D |=======|____|________________________|_______________________|_______________________|_______________________|_______________________|_______________________|_
__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__|__________________________|_______________________|_______________________|_______________________|_______________________|_______________________|
|/-=|___|= || || || |_____/~\\___/ |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_|
\\_/ \\O=====O=====O=====O_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/`;
export default function SlBackground() {
const [pos, setPos] = useState(150);
useEffect(() => {
let animationFrameId: number;
let lastTime = 0;
const animate = (timestamp: number) => {
if (!lastTime) lastTime = timestamp;
const delta = timestamp - lastTime;
// Update position every ~30ms to create a retro sliding terminal refresh feel
if (delta > 45) {
setPos((prev) => {
if (prev <= -150) return 150;
return prev - 1.5;
});
lastTime = timestamp;
}
animationFrameId = requestAnimationFrame(animate);
};
animationFrameId = requestAnimationFrame(animate);
return () => cancelAnimationFrame(animationFrameId);
}, []);
return (
<>
<style>
{`
@keyframes rainbowShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
`}
</style>
<div
className="sl-background"
style={{
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
pointerEvents: "none",
zIndex: 0,
overflow: "hidden",
display: "flex",
alignItems: "flex-end",
paddingBottom: "5vh",
justifyContent: "center",
userSelect: "none",
backgroundImage: "linear-gradient(rgba(29, 32, 33, 0.94), rgba(29, 32, 33, 0.94)), url('/gruvbox.webp')",
backgroundSize: "cover",
backgroundPosition: "center",
}}
>
<pre
style={{
margin: 0,
whiteSpace: "pre",
fontFamily: "var(--font-custom-mono), monospace",
fontSize: "1rem",
transform: "translateX(" + pos + "vw)",
willChange: "transform",
background: "linear-gradient(90deg, var(--red), var(--accent2), var(--accent), var(--green), var(--aqua), var(--blue), var(--purple))",
backgroundSize: "200% auto",
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
animation: "rainbowShift 3s linear infinite",
opacity: 0.35,
filter: "drop-shadow(0 0 12px rgba(250, 189, 47, 0.5))",
}}
>
{TRAIN_ASCII}
</pre>
</div>
</>
);
}

View file

@ -0,0 +1,603 @@
import Image from "next/image";
import type { CSSProperties } from "react";
import SlBackground from "./SlBackground";
import JokerLogo from "./JokerLogo";
import ServiceButton from "./ServiceButton";
import ContributionHeatmap from "./ContributionHeatmap";
import { useTheme } from "./useTheme";
import { socials, codingProjects, techProjects, friends } from "../data";
type PanelStyle = CSSProperties & { "--panel-color"?: string };
const panelStyle = (color: string, style: CSSProperties = {}): PanelStyle => ({
...style,
"--panel-color": color,
});
export default function TerminalLayout() {
const { toggle } = useTheme();
return (
<>
<SlBackground />
<div className="container">
<header className="header">
<div className="header-center">
<JokerLogo />
<h1 className="site-name">dvorakmortonxd.dev</h1>
<button type="button" className="header-theme-btn" onClick={toggle}>
Desktop
</button>
</div>
</header>
<main className="hero">
<div className="hero-panel" style={panelStyle("var(--accent)")}>
<span
className="hero-panel-label"
style={{ color: "var(--accent)", borderColor: "var(--accent)" }}
>
README.MD
</span>
<h2 className="hero-title">$ whoami</h2>
<p className="hero-subtitle">
Welcome my personal website! Here I show off my projects and hardware I own,
aswell as my self-hosted services :)<span className="cursor-blink"></span>
</p>
</div>
<div className="social-section">
<div className="tui-panel" style={panelStyle("var(--accent)")}>
<span
className="tui-panel-label"
style={{ color: "var(--accent)", borderColor: "var(--accent)" }}
>
SOCIALS.JS
</span>
<div className="social-buttons">
{socials.map((s) => (
<a
key={s.name}
href={s.url}
target="_blank"
rel="noopener noreferrer"
className="social-button"
>
<Image
src={s.icon}
alt={s.name}
width={16}
height={16}
className="social-icon"
/>
<span className="social-label">{s.name}</span>
</a>
))}
</div>
<div className="mail-contact">
mail if u ever wanna contact me:{" "}
<a href="mailto:dvorak@dvorakmortonxd.dev">dvorak@dvorakmortonxd.dev</a>
</div>
</div>
</div>
<div className="gym-section">
<div className="tui-panel" style={panelStyle("var(--white)")}>
<span
className="tui-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
GYM_SBD_AT_73KG_BW.DB
</span>
<div className="gym-grid">
<div className="gym-item">
<Image src="/squat.svg" alt="Squat" width={48} height={48} className="gym-icon" />
<div className="gym-label">SQUAT</div>
<div className="gym-weight">125kg</div>
<div className="gym-date">5.1.2025</div>
</div>
<div className="gym-item">
<Image src="/bench.svg" alt="Bench" width={48} height={48} className="gym-icon" />
<div className="gym-label">BENCH</div>
<div className="gym-weight">111kg</div>
<div className="gym-date">29.5.2026</div>
</div>
<div className="gym-item">
<Image
src="/deadlift.svg"
alt="Deadlift"
width={48}
height={48}
className="gym-icon"
/>
<div className="gym-label">DEADLIFT</div>
<div className="gym-weight">165kg</div>
<div className="gym-date">17.12.2024</div>
</div>
</div>
</div>
</div>
<div className="about-section">
<div className="tui-panel" style={panelStyle("var(--white)")}>
<span
className="tui-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
NOW.TXT
</span>
<div className="about-content">
<p>
<span style={{ color: "var(--green)" }}>martin@dvorakmortonxd</span>:
<span className="text-blue">~</span>$ cat now.txt
</p>
<div style={{ color: "#a3a3a3" }}>
<p>
I&#39;m currently hosting an SMP (dm me on discord). Also I&#39;m pretty
much cooking daily, because im bulking through out the non-summer seasons.
And me and my pal <a href="https://skopec.dev">Pepa</a> are working on an
education app so we can study more efficiently, It&#39;s called{" "}
<a href="https://git.dvorakmortonxd.dev/edu/maturita.c">maturita.c</a>!
</p>
</div>
</div>
</div>
</div>
<div className="about-section">
<div className="tui-panel" style={panelStyle("var(--accent)")}>
<span
className="tui-panel-label"
style={{ color: "var(--accent)", borderColor: "var(--accent)" }}
>
README.MD
</span>
<div className="about-content">
<p>
<span className="text-green">martin@dvorakmortonxd</span>:
<span className="text-blue">~</span>$ cat about_me.md
</p>
<div style={{ color: "#a3a3a3" }}>
<p>
Hey, I&#39;m Martin Dvořák — a 17(soon to be 18)-year-old IT student based
in the Czech Republic, specializing in network management and
administration at <a href="https://sssvt.cz">sssvt.cz</a>. I&#39;m a
sophomore and I have wanted to go to this school since 7th grade (2022) so
I&#39;m happy I got in in 2025, the school is pretty cool so if you are in
middle school and interested in IT, make sure to check it out. I&#39;m a
homelabber and developer heavily focused on self-hosting{" "}
<i>literally everything</i>, writing code (for example games for gamejams),
tinkering with GNU/Linux or Musl/Linux systems and retro hardware. I own a
small collection of laptops ranging from 2009 to 2014 (and ofcourse my 2025
macbook), most of these found in ewaste. In my free time I mostly spend
time with my gf {"<"}3, I also spend a bit of time setting up my self
hosted stuff (like jellyfin or gitdxd), and also when I&#39;m in my gaming
mood I play terraria (around 1300hr playtime btw) and minecraft modpacks
with mekanism and/or create. I also go to the gym around 3-5 times a week,
running a PPL split focused on strength/powerlifting and especially SBD. I
take a big focus on my health and physique.
<span className="cursor-blink"></span>
</p>
</div>
</div>
</div>
</div>
<div className="services-section">
<div className="tui-panel" style={panelStyle("var(--accent)")}>
<span
className="tui-panel-label"
style={{ color: "var(--accent)", borderColor: "var(--accent)" }}
>
SERVICES.HTML
</span>
<div className="services-buttons services-main">
<ServiceButton
url="https://proxmox.dvorakmortonxd.dev/"
className="proxmox"
icon="🖥️"
name="Proxmox"
desc="Server Management"
access="private"
disabled
/>
<ServiceButton
url="https://ai.dvorakmortonxd.dev/"
className="ai"
icon="🦾"
name="Llama.cpp"
desc="Local AI Server"
access="on_request"
/>
<ServiceButton
url="https://jelly.dvorakmortonxd.dev/"
className="jellyfin"
icon="🎬"
name="Jellyfin"
desc="Local Media Server"
access="on_request"
/>
<ServiceButton
url="https://discord.gg/vyvhk7d8bX"
checkUrl="minecraft://mc.dvorakmortonxd.dev:25565"
className="pterodactyl"
icon="🎮"
name="SMP"
desc="My Survival Minecraft Server"
access="on_request"
/>
<ServiceButton
url="https://navidrome.dvorakmortonxd.dev/"
className="funkwhale"
icon="🎸"
name="Navidrome"
desc="Music Streaming"
access="private"
/>
<ServiceButton
url="https://git.dvorakmortonxd.dev"
className="gitdxd"
icon="🐙"
name="GitDXD"
desc="Best Git Hosting OAT"
access="public"
/>
</div>
</div>
</div>
<div className="gitdxd-section" style={{ marginTop: "20px" }}>
<div className="tui-panel" style={panelStyle("var(--white)")}>
<span
className="tui-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
GITDXD.GIT
</span>
<div style={{ padding: "24px 16px 16px" }}>
<h2
style={{
fontSize: "2.4rem",
fontWeight: "bold",
color: "var(--white)",
marginBottom: "16px",
textAlign: "center",
}}
>
GitDXD
</h2>
<p
style={{
fontSize: "1.8rem",
color: "var(--white)",
fontWeight: "500",
textAlign: "center",
}}
>
My Self-hosted Git Instance
</p>
<div
style={{
marginTop: "16px",
marginBottom: "16px",
borderRadius: "8px",
overflow: "hidden",
border: "1px solid rgba(255, 255, 255, 0.4)",
boxShadow: "0 0 30px rgba(180, 255, 125, 0.15)",
}}
>
<Image
src="/gitdxd.webp"
alt="GitDXD Preview"
width={1280}
height={720}
style={{ width: "100%", height: "auto", display: "block" }}
/>
</div>
<div
style={{
color: "var(--gray)",
marginTop: "12px",
lineHeight: "1.6",
textAlign: "center",
}}
>
<p>
My very own forgejo git instance, originally started as a private git
instance for me and my friends to boycott GitHub but I&#39;ve made it
public now so. Join at{" "}
<span className="text-purple-500">
<a href="https://git.dvorakmortonxd.dev">git.dvorakmortonxd.dev</a>
</span>
.<span className="cursor-blink"></span>
</p>
</div>
</div>
</div>
</div>
<div className="commits-section" style={{ marginTop: "20px" }}>
<div className="tui-panel" style={panelStyle("var(--accent)")}>
<span
className="tui-panel-label"
style={{ color: "var(--accent)", borderColor: "var(--accent)" }}
>
CONTRIBUTIONS@GITDXD.GIT
</span>
<div className="commits-content" style={{ padding: "24px 12px 16px" }}>
<ContributionHeatmap />
</div>
</div>
</div>
<div className="revival-section" style={{ marginTop: "20px" }}>
<div className="tui-panel" style={panelStyle("var(--white)")}>
<span
className="tui-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
REVIVAL.INC
</span>
<div style={{ padding: "24px 16px 16px" }}>
<h2
style={{
fontSize: "2.4rem",
fontWeight: "bold",
color: "var(--white)",
marginBottom: "32px",
textAlign: "center",
}}
>
Revival inc.
</h2>
<div
style={{
marginTop: "12px",
marginBottom: "12px",
borderRadius: "8px",
overflow: "hidden",
border: "1px solid rgba(0, 0, 0, 0.4)",
boxShadow: "0 0 30px rgba(255, 255, 255, 0.35)",
width: "80%",
margin: "12px auto",
}}
>
<Image
src="/revivalinc.webp"
alt="revival inc thumbnail"
width={768}
height={576}
style={{ width: "100%", height: "auto", display: "block" }}
/>
</div>
<p
style={{
fontSize: "1.8rem",
color: "var(--white)",
fontWeight: "500",
textAlign: "center",
}}
>
What is it?
</p>
<div style={{ color: "var(--gray)", marginTop: "12px", lineHeight: "1.6" }}>
<p>
It&#39;s a game I made for the game jam &#34;Mini Jame Gam #55&#34;, the
theme was Necromancy and the special item was Milk, the game also includes
a tutorial so if you wanna try it do it. Check it out at{" "}
<span className="text-purple-500">
<a href="https://martin-dv.itch.io/revival-inc">itch.io</a>
</span>{" "}
or play{" "}
<span className="text-purple-500">
<a href="https://dvorakmortonxd.dev/revival-inc">here</a>
</span>
.<span className="cursor-blink"></span>
</p>
</div>
</div>
</div>
</div>
<div className="rustywolf-section" style={{ marginTop: "20px" }}>
<div className="tui-panel" style={panelStyle("var(--white)")}>
<span
className="tui-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
RUSTYWOLF.RS
</span>
<div style={{ padding: "24px 16px 16px" }}>
<h2
style={{
fontSize: "2.4rem",
fontWeight: "bold",
color: "var(--white)",
marginBottom: "32px",
textAlign: "center",
}}
>
Introducing RustyWolf
</h2>
<div
style={{
marginTop: "12px",
marginBottom: "12px",
borderRadius: "8px",
overflow: "hidden",
border: "1px solid rgba(255, 255, 255, 0.4)",
boxShadow: "0 0 30px rgba(255, 255, 255, 0.2)",
}}
>
<Image
src="/RustyWolfPreview.webp"
alt="RustyWolf Browser Preview"
width={1280}
height={720}
style={{ width: "100%", height: "auto", display: "block" }}
/>
</div>
<p
style={{
fontSize: "1.8rem",
color: "var(--white)",
fontWeight: "500",
textAlign: "center",
}}
>
What makes it so cool???
</p>
<div style={{ color: "var(--gray)", marginTop: "12px", lineHeight: "1.6" }}>
<p>
A lightweight browser made in Rust with WebKitGTK. It&#39;s the successor
to my previous project Venturesome, aiming to provide a fast and minimalist
browsing experience. It&#39;s a perfect browser for old machines that
struggle with modern browsers. Check it out at{" "}
<span style={{ color: "var(--accent2)" }}>
<a href="https://git.dvorakmortonxd.dev/dvorakmortonxd/RustyWolf">
GitDXD
</a>
</span>
.<span className="cursor-blink"></span>
</p>
</div>
</div>
</div>
</div>
</main>
<section className="projects">
<div className="subsection-wrapper">
<div className="subsection-panel" style={panelStyle("var(--white)")}>
<span
className="subsection-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
TECH_LIST.JSON
</span>
<h2
style={{
fontSize: "2rem",
fontWeight: "bold",
textAlign: "center",
margin: "4px 0 20px",
color: "var(--white)",
}}
>
All my hardware equipment :)
</h2>
<div className="project-grid">
{techProjects.map((project) => (
<div key={project.title} className="project-card">
<div
className="project-image"
style={{ backgroundImage: `url(${project.image})` }}
/>
<h4 className="project-title">{project.title}</h4>
<p className="project-desc">{project.desc}</p>
</div>
))}
</div>
</div>
</div>
<div className="subsection-wrapper">
<div className="subsection-panel coding-panel" style={panelStyle("var(--accent)")}>
<span
className="subsection-panel-label"
style={{ color: "var(--accent)", borderColor: "var(--accent)" }}
>
PROJECTS.DOCX
</span>
<h2
style={{
fontSize: "2rem",
fontWeight: "bold",
textAlign: "center",
margin: "4px 0 20px",
color: "var(--accent)",
}}
>
All the stuff I&#39;ve worked on :))
</h2>
<div className="project-grid">
{codingProjects.map((project, idx) => (
<a
key={idx}
href={project.url}
target="_blank"
rel="noopener noreferrer"
className="project-card"
>
<div
className="project-image"
style={{ backgroundImage: `url(${project.img})` }}
/>
<h4 className="project-title">{project.title}</h4>
<p className="project-desc">{project.desc}</p>
</a>
))}
</div>
</div>
</div>
<div className="subsection-wrapper">
<div
className="subsection-panel friends-panel"
style={panelStyle("var(--white)", { backgroundColor: "rgba(255, 255, 255, 0.02)" })}
>
<span
className="subsection-panel-label"
style={{ color: "var(--white)", borderColor: "var(--white)" }}
>
FRIENDS.TSX
</span>
<h2
style={{
fontSize: "2rem",
fontWeight: "bold",
textAlign: "center",
margin: "4px 0 20px",
color: "var(--white)",
}}
>
Friend&#39;s websites and projects
</h2>
<div className="services-buttons" style={{ gap: "1rem" }}>
{friends.map((friend, idx) => (
<ServiceButton
key={idx}
url={friend.realUrl || friend.url}
className="friend"
icon={
<Image
src={friend.img}
alt={friend.name}
width={68}
height={68}
className="friend-icon"
style={{
borderRadius: "50%",
filter:
"brightness(0) invert(65%) hue-rotate(70deg) saturate(100%)",
}}
/>
}
name={friend.name}
desc={friend.desc}
/>
))}
</div>
</div>
</div>
</section>
<footer className="footer">
<span className="footer-label">v2.1.0</span>
© 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just follow
the GPL3.0 License)
</footer>
</div>
</>
);
}

View file

@ -1,57 +1,32 @@
"use client";
import { useEffect, useState } from "react";
import { setTheme, useTheme } from "./useTheme";
import SkeuoLayout from "./SkeuoLayout";
import { useTheme } from "./useTheme";
import TerminalLayout from "./TerminalLayout";
import WindowsDesktop from "./WindowsDesktop";
import MobileHome from "./MobileHome";
export default function ThemeRoot() {
const { theme } = useTheme();
const [phone, setPhone] = useState(false);
// The desktop simulation only exists on phone-sized viewports. On anything
// wider the page is always the skeuo theme, and a stale "desktop"
// preference is overridden here so nobody is stuck in a mode whose switch
// they cannot reach.
useEffect(() => {
if (typeof window.matchMedia !== "function") return;
const mq = window.matchMedia("(max-width: 768px)");
const sync = () => {
setPhone(mq.matches);
if (!mq.matches && document.documentElement.getAttribute("data-theme") === "desktop") {
setTheme("skeuo");
}
};
sync();
mq.addEventListener("change", sync);
return () => mq.removeEventListener("change", sync);
}, []);
const desktop = theme === "desktop";
const terminal = theme === "terminal";
// The desktop is kept mounted (just hidden) while the Gruvbox/terminal theme
// is active. That way the Welcome window is only created on a fresh page
// load and isn't reopened by toggling themes.
return (
<>
{/*
The skeuo theme stays mounted (just hidden) while the desktop is up so
its scroll position survives a toggle. The desktop is mounted once the
viewport is known to be a phone and then kept mounted, so the Welcome
window is only created on demand and isn't reopened by toggling.
*/}
<div className="sk-shell" style={desktop ? { display: "none" } : undefined}>
<SkeuoLayout />
<div
className="skeuo-desktop-root"
style={terminal ? { display: "none" } : undefined}
>
<WindowsDesktop />
</div>
{phone ? (
<>
<div className="skeuo-desktop-root" style={desktop ? undefined : { display: "none" }}>
<WindowsDesktop />
</div>
<div className="skeuo-mobile-root" style={desktop ? undefined : { display: "none" }}>
<MobileHome />
</div>
</>
) : null}
<div
className="skeuo-mobile-root"
style={terminal ? { display: "none" } : undefined}
>
<MobileHome />
</div>
{terminal && <TerminalLayout />}
</>
);
}

View file

@ -7,27 +7,7 @@ import { useServerInsertedHTML } from "next/navigation";
// without a flash. It is injected with useServerInsertedHTML so the <script>
// lives in the SSR HTML stream instead of inside the React tree — React 19
// logs an error for script tags rendered by components on the client.
//
// Theme ids were renamed (skeuo = the site, desktop = the KDE sim) and the
// storage key moved from `theme` to `dmx-theme`, so this migrates the old
// values once: terminal -> skeuo, skeuo -> desktop.
const INIT_SCRIPT = `(function(){try{
var d=document.documentElement;
var mq=window.matchMedia('(max-width:768px)');
var stored=null;
try{stored=localStorage.getItem('dmx-theme');}catch(e){}
if(stored!=='skeuo'&&stored!=='desktop'){
var legacy=null;
try{legacy=localStorage.getItem('theme');}catch(e){}
if(legacy==='terminal'||legacy==='skeuo')stored=legacy==='terminal'?'skeuo':'desktop';
if(legacy!==null){try{localStorage.setItem('dmx-theme',stored||'skeuo');localStorage.removeItem('theme');}catch(e){}}
}
var theme=(stored==='desktop'&&mq.matches)?'desktop':'skeuo';
d.setAttribute('data-theme',theme);
var ua=navigator.userAgent||'';
var phone=/(iPhone|iPod|Android.+Mobile|Windows Phone|IEMobile|BlackBerry|Opera Mini|Mobile)/i.test(ua);
d.setAttribute('data-device',phone?'phone':'desktop');
}catch(e){}})();`;
const INIT_SCRIPT = `(function(){try{var t=localStorage.getItem('theme');if(t==='terminal'||t==='skeuo'){document.documentElement.setAttribute('data-theme',t);}var ua=navigator.userAgent||'';var phone=/(iPhone|iPod|Android.+Mobile|Windows Phone|IEMobile|BlackBerry|Opera Mini|Mobile)/i.test(ua);document.documentElement.setAttribute('data-device',phone?'phone':'desktop');}catch(e){}})();`;
export default function ThemeScript() {
// useServerInsertedHTML can fire several times during a single render pass;

View file

@ -577,10 +577,10 @@ export default function WindowsDesktop() {
type="button"
className="win-theme-toggle"
onClick={toggle}
title={`Switch to ${theme === "desktop" ? "skeuo" : "Desktop"} theme`}
title={`Switch to ${theme === "skeuo" ? "gruvbox" : "Desktop"} theme`}
>
<span aria-hidden="true">{theme === "desktop" ? "▚" : "❖"}</span>
<span>{theme === "desktop" ? "Skeuo" : "Desktop"}</span>
<span aria-hidden="true">{theme === "skeuo" ? "▚" : "❖"}</span>
<span>{theme === "skeuo" ? "Gruvbox" : "Desktop"}</span>
</button>
<Clock className="win-clock" />

View file

@ -46,14 +46,14 @@ function WelcomeApp() {
<li>Drag windows around by their title bar.</li>
<li>Use the buttons at the top-right to minimize, maximize or close.</li>
<li>Open apps from the Gentoo launcher, bottom-left.</li>
<li>Switch back to the skeuo theme from the panel tray, bottom-right.</li>
<li>Switch back to the Gruvbox theme from the panel tray, bottom-right.</li>
</ul>
<p className="app-preference">
If you&#39;d prefer a normal website{" "}
<button
type="button"
className="app-inline-link"
onClick={() => setTheme("skeuo")}
onClick={() => setTheme("terminal")}
>
click here
</button>

View file

@ -2,15 +2,7 @@
import { useSyncExternalStore } from "react";
/** `skeuo` is the site itself; `desktop` is the phone-only KDE simulation. */
export type Theme = "skeuo" | "desktop";
/** Width at or below which the desktop-mode switch is offered. */
export const DESKTOP_MODE_MAX_WIDTH = 768;
/** Renamed with the theme (was `theme`); ThemeScript migrates the old key. */
export const THEME_KEY = "dmx-theme";
export const LEGACY_THEME_KEY = "theme";
export type Theme = "skeuo" | "terminal";
const EVENT = "theme-change";
@ -24,27 +16,20 @@ function subscribe(callback: () => void) {
}
function getSnapshot(): Theme {
return document.documentElement.getAttribute("data-theme") === "desktop" ? "desktop" : "skeuo";
return document.documentElement.getAttribute("data-theme") === "terminal"
? "terminal"
: "skeuo";
}
function getServerSnapshot(): Theme {
return "skeuo";
}
/** True only on viewports that are allowed to run the desktop simulation. */
export function allowsDesktopMode() {
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
return window.matchMedia(`(max-width: ${DESKTOP_MODE_MAX_WIDTH}px)`).matches;
}
export function setTheme(theme: Theme) {
if (typeof document === "undefined") return;
// Wide viewports can never enter (or stay in) the desktop sim: the switch is
// hidden there, so there would be no way back.
const next = theme === "desktop" && !allowsDesktopMode() ? "skeuo" : theme;
document.documentElement.setAttribute("data-theme", next);
document.documentElement.setAttribute("data-theme", theme);
try {
localStorage.setItem(THEME_KEY, next);
localStorage.setItem("theme", theme);
} catch {
/* ignore */
}
@ -55,7 +40,6 @@ export function useTheme() {
const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
return {
theme,
setTheme,
toggle: () => setTheme(theme === "skeuo" ? "desktop" : "skeuo"),
toggle: () => setTheme(theme === "skeuo" ? "terminal" : "skeuo"),
};
}

File diff suppressed because it is too large Load diff

View file

@ -1,28 +1,8 @@
import type { Metadata } from "next";
import { Barlow_Semi_Condensed, Courier_Prime } from "next/font/google";
// Removed unused google fonts since we use local Custom Mono
import "./globals.css";
import ThemeScript from "./components/ThemeScript";
// The skeuo theme's two voices: an engraved-panel grotesque for metal
// (labels, headings, controls) and a typewriter for anything on paper.
// Both get an explicit fallback stack so the page still reads correctly
// if the webfont never arrives.
const panel = Barlow_Semi_Condensed({
variable: "--font-panel",
subsets: ["latin"],
weight: ["500", "600", "700"],
display: "swap",
fallback: ["Arial Narrow", "Helvetica Neue", "Arial", "sans-serif"],
});
const typewriter = Courier_Prime({
variable: "--font-typewriter",
subsets: ["latin"],
weight: ["400", "700"],
display: "swap",
fallback: ["Courier New", "Courier", "monospace"],
});
export const metadata: Metadata = {
title: "dvorakmortonxd.dev",
description: "Martin Dvořák's personal website.",
@ -45,12 +25,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html
lang="en"
data-theme="skeuo"
suppressHydrationWarning
className={`${panel.variable} ${typewriter.variable}`}
>
<html lang="en" data-theme="skeuo" suppressHydrationWarning>
<body className="antialiased">
<ThemeScript />
{children}

View file

@ -1,21 +1,3 @@
/* ============================================================
SHARED COMPONENT SHEET
------------------------------------------------------------
Styles for the components both shells render: ServiceButton,
ContributionHeatmap, JokerLogo, the project cards and the
social buttons.
- the skeuo theme (skeuo.css) overrides them scoped to
`html[data-theme="skeuo"]`
- the KDE desktop mode (desktop.css) overrides them scoped to
`.app-surface` / `.win-body` inside its windows
The `:root` block below is only the fallback those components
inherit where a shell overrides nothing; each shell defines
its own palette on top of it.
============================================================ */
/* Monocraft is loaded for the desktop mode's terminal-style windows. */
@font-face {
font-family: 'Monocraft';
src: url('/Monocraft.ttf') format('truetype');
@ -38,22 +20,21 @@
}
:root {
/* fallback palette for the shared components (never seen on its own —
the skeuo theme and the desktop mode both define their own) */
/* Gruvbox Dark Theme */
--bg: #1d2021;
--bg-soft: #282828;
--bg-hard: #32302f;
--fg: #ebdbb2;
--gray: #a89984;
--prettypurple: #733999;
--accent: #fabd2f; /* fallback amber */
--accent2: #fe8019; /* fallback orange */
--accent3: #d79921; /* fallback deep amber */
--green: #b8bb26; /* fallback green */
--aqua: #8ec07c; /* fallback aqua */
--blue: #83a598; /* fallback blue */
--purple: #d3869b; /* fallback purple */
--red: #fb4934; /* fallback red */
--accent: #fabd2f; /* Gruvbox Yellow */
--accent2: #fe8019; /* Gruvbox Orange */
--accent3: #d79921; /* Gruvbox Dark Yellow */
--green: #b8bb26; /* Gruvbox Green */
--aqua: #8ec07c; /* Gruvbox Aqua */
--blue: #83a598; /* Gruvbox Blue */
--purple: #d3869b; /* Gruvbox Purple */
--red: #fb4934; /* Gruvbox Red */
--darkpink: #ff0043; /* Custom Dark Pink */
--font-custom-mono: 'Monocraft', 'JetBrains Mono', 'Fira Code', 'Source Code Pro', 'Courier New', monospace;
--card-bg: rgba(40, 40, 40, 0.65);
@ -1253,3 +1234,23 @@ body {
}
}
/* ============================================
HEADER THEME SWITCH (terminal theme)
============================================ */
.header-theme-btn {
margin-left: auto;
padding: 4px 12px;
background: transparent;
border: 1px solid var(--gray);
color: var(--fg);
font-family: var(--font-custom-mono), 'JetBrains Mono', monospace;
font-size: 0.75rem;
cursor: pointer;
transition: all 0.15s ease;
}
.header-theme-btn:hover {
border-color: var(--accent);
color: var(--accent);
box-shadow: 0 0 8px rgba(250, 189, 47, 0.35);
}

View file

@ -1,7 +1,6 @@
import { Metadata } from 'next';
import './shared.css';
import './page.css';
import './skeuo.css';
import './desktop.css';
import ThemeRoot from './components/ThemeRoot';
export const metadata: Metadata = {

File diff suppressed because it is too large Load diff