redraw the desk as cartoon skeuomorphism: CSS-only materials (no textures), light cream desk, per-item hues, cork board, receipt, scoreboard

This commit is contained in:
Martin Dvořák 2026-09-30 09:59:00 +00:00
commit 1880a5b0db
14 changed files with 1165 additions and 989 deletions

View file

@ -27,6 +27,17 @@ const NAV = [
{ href: "#contact", label: "contact" },
];
/** One hue per item, so every list reads as separate pieces of hardware. */
const TONES = [
"var(--orange)",
"var(--teal)",
"var(--blue)",
"var(--lilac)",
"var(--mint)",
"var(--coral)",
"var(--yellow)",
];
const SERVICES: {
name: string;
desc: string;
@ -72,11 +83,11 @@ export default function WebSite() {
return (
<div className="w-page">
{/* -------------------------------------------------------------- rail */}
<header className="w-rail w-mt-metal-flush" style={{ borderRadius: 0 }}>
<header className="w-rail">
<div className="mx-auto flex h-16 w-full max-w-[1120px] items-center gap-5 px-5 sm:px-8">
<a href="#top" className="flex shrink-0 items-center gap-2.5" aria-label="Back to top">
<Led kind="on" pulse slow />
<span className="w-wordmark w-engrave">dvorakmortonxd</span>
<span className="w-wordmark">dvorakmortonxd</span>
</a>
<nav className="ml-auto hidden items-center gap-6 md:flex" aria-label="Main">
@ -95,7 +106,7 @@ export default function WebSite() {
className="desktop-toggle flex items-center gap-3"
title="Flip to Desktop mode"
>
<span className="w-mono hidden text-[0.6rem] tracking-[0.2em] text-[var(--ftext-faint)] sm:inline">
<span className="w-mono hidden text-[0.6rem] tracking-[0.2em] text-[var(--ink-soft)] sm:inline">
DESKTOP
</span>
<span className="w-rocker">
@ -110,7 +121,7 @@ export default function WebSite() {
onClick={() => setMenuOpen((v) => !v)}
aria-expanded={menuOpen}
aria-label={menuOpen ? "Close menu" : "Open menu"}
className="w-keybtn !px-3 !py-2"
className="w-keybtn"
>
{menuOpen ? "close" : "menu"}
</button>
@ -120,7 +131,7 @@ export default function WebSite() {
{menuOpen ? (
<nav
className="w-mt-metal-flush mx-auto mb-3 flex w-[calc(100%-2.5rem)] max-w-[1120px] flex-col gap-1 rounded-lg p-3 md:hidden"
className="w-plastic mx-auto mb-3 flex w-[calc(100%-2.5rem)] max-w-[1120px] flex-col gap-1 p-3 md:hidden"
aria-label="Main"
>
{NAV.map((item) => (
@ -128,7 +139,7 @@ export default function WebSite() {
key={item.href}
href={item.href}
onClick={() => setMenuOpen(false)}
className="w-mono border-b border-[rgba(255,226,180,0.07)] py-3 text-[0.78rem] text-[var(--ftext-dim)] last:border-b-0"
className="w-display border-b-2 border-dashed border-[var(--plastic-edge)] py-3 text-[0.9rem] text-[var(--plastic-ink)] last:border-b-0"
>
{item.label}
</a>
@ -149,18 +160,18 @@ export default function WebSite() {
<span className="a">martin@dvorakmortonxd</span>:~$ whoami
<span className="w-caret ml-2" />
</p>
<h1 className="w-display mt-5 text-[clamp(1.8rem,4.1vw,2.75rem)] text-[var(--ftext)]">
<h1 className="w-display mt-5 text-[clamp(1.8rem,4.1vw,2.75rem)] text-[var(--glass-ink)]">
My own little internet — one rack, zero subscriptions.
</h1>
<p className="w-prose mt-5 max-w-[54ch] text-[var(--ftext-dim)]">
<p className="w-prose mt-5 max-w-[54ch] text-[var(--glass-dim)]">
I&rsquo;m Martin Dvořák. Git, media, music, an AI box and a Minecraft server all run on a
Proxmox machine in my room — plus the hardware graveyard I keep rescuing from e-waste.
</p>
<p className="mt-7 flex flex-wrap gap-x-8 gap-y-3">
<p className="mt-7 flex flex-wrap gap-3">
<a href="#services" className="w-cmd">
$ open rack --services
</a>
<a href="#projects" className="w-cmd">
<a href="#projects" className="w-cmd w-cmd--quiet">
$ open drawer --projects
</a>
</p>
@ -175,10 +186,10 @@ export default function WebSite() {
<div className="flex flex-col gap-6">
<MiniRack />
<div className="grid grid-cols-2 gap-3">
<Plaque value={String(SERVICES.length)} label="services" />
<Plaque value={String(codingProjects.length)} label="projects" />
<Plaque value={String(techProjects.length)} label="machines" />
<Plaque value="401" label="kg best SBD" />
<Plaque value={String(SERVICES.length)} label="services" tone="var(--orange)" />
<Plaque value={String(codingProjects.length)} label="projects" tone="var(--teal)" />
<Plaque value={String(techProjects.length)} label="machines" tone="var(--blue)" />
<Plaque value="401" label="kg best SBD" tone="var(--coral)" />
</div>
</div>
</Reveal>
@ -193,7 +204,7 @@ export default function WebSite() {
</Reveal>
<div className="grid gap-7 lg:grid-cols-[minmax(0,1.55fr)_minmax(0,1fr)] lg:items-start">
<Reveal delay={60}>
<article className="w-mt-paper w-sheet">
<article className="w-paper w-sheet">
<div className="w-sheet__head">
<span>manifest.txt</span>
<span className="ml-auto">printed on the desk</span>
@ -224,15 +235,13 @@ export default function WebSite() {
</Reveal>
<Reveal delay={150}>
<aside className="w-mt-paper w-cardindex lg:mt-12">
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[var(--ink-soft)]">
INDEX CARD
</p>
<p className="w-serif mt-3 text-[1.15rem] text-[var(--ink)]">
<aside className="w-paper w-cardindex lg:mt-14" style={{ "--tone": "var(--teal)" } as CSSProperties}>
<p className="w-kicker">index card</p>
<p className="w-serif mt-3 text-[1.2rem] text-[var(--ink)]">
&ldquo;If it has a fan, I&rsquo;ll find a use for it.&rdquo;
</p>
<div className="w-rule my-4" />
<ul className="w-mono space-y-2 text-[0.66rem] text-[var(--ink-soft)]">
<ul className="w-mono space-y-2 text-[0.68rem] text-[var(--ink-soft)]">
<li>school · sssvt.cz</li>
<li>gym · PPL 3–5×/week</li>
<li>games · Terraria, Minecraft</li>
@ -251,14 +260,13 @@ export default function WebSite() {
<div className="grid gap-7 lg:grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)] lg:items-start">
<Reveal delay={60}>
<div className="w-note">
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[#6b7075]">
NOW.TXT · UPDATED 09/2026
</p>
<p className="w-prose mt-4 text-[#34383b]">
<span className="w-pin" aria-hidden="true" />
<p className="w-kicker !text-[#8a7420]">now.txt · updated 09/2026</p>
<p className="w-prose mt-4 text-[#5c4a1f]">
I&rsquo;m hosting an SMP — message me on Discord if you want in. I&rsquo;m also cooking most
days, bulking through the non-summer seasons.
</p>
<p className="w-prose mt-3 text-[#34383b]">
<p className="w-prose mt-3 text-[#5c4a1f]">
Me and my friend{" "}
<a className="w-link" href="https://skopec.dev" target="_blank" rel="noopener noreferrer">
Pepa
@ -278,24 +286,25 @@ export default function WebSite() {
</Reveal>
<Reveal delay={140}>
<div className="flex flex-col gap-6">
<div className="w-mt-paper w-cardindex w-cardindex--alt">
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[var(--ink-soft)]">
BENCH STATUS
</p>
<ul className="w-mono mt-3 space-y-2 text-[0.7rem] text-[var(--ink)]">
<li className="flex items-center gap-2">
<div className="flex flex-col gap-8">
<div className="w-paper w-cardindex w-cardindex--alt" style={{ "--tone": "var(--coral)" } as CSSProperties}>
<p className="w-kicker">bench status</p>
<ul className="w-display mt-4 space-y-2.5 text-[0.82rem] text-[var(--ink)]">
<li className="flex items-center gap-2.5">
<Led kind="on" /> smp · accepting players
</li>
<li className="flex items-center gap-2">
<li className="flex items-center gap-2.5">
<Led kind="amber" pulse /> maturita.c · in development
</li>
<li className="flex items-center gap-2">
<li className="flex items-center gap-2.5">
<Led kind="on" /> gym · PPL 3–5×/week
</li>
</ul>
</div>
<i className="w-pen ml-6 w-44" aria-hidden="true" />
<div className="flex items-end gap-6">
<i className="w-pen mb-3 w-40" aria-hidden="true" />
<span className="w-mug mr-6" aria-hidden="true" />
</div>
</div>
</Reveal>
</div>
@ -307,11 +316,13 @@ export default function WebSite() {
<SectionHead index="03" label="rack" title="Six machines, one shelf" />
</Reveal>
<Reveal delay={60}>
<div className="w-mt-metal w-rack">
<div className="w-chassis w-rack">
<div className="w-rack__top">
<Led kind="on" pulse slow />
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">RACK 01 · SERVICES</span>
<span className="w-mono ml-auto hidden text-[0.6rem] tracking-[0.14em] text-[var(--ftext-faint)] sm:inline">
<span className="w-display text-[0.7rem] tracking-[0.18em] text-[var(--chassis-ink)]">
RACK 01 · SERVICES
</span>
<span className="w-mono ml-auto hidden text-[0.62rem] tracking-[0.12em] text-[var(--chassis-faint)] sm:inline">
health checked from this page
</span>
<span className="w-rack__vent w-vents" />
@ -319,8 +330,8 @@ export default function WebSite() {
<div className="w-rack__grid">
<span className="w-rails" />
<div>
{SERVICES.map((s) => (
<ServiceUnit key={s.name} {...s} />
{SERVICES.map((s, i) => (
<ServiceUnit key={s.name} tone={TONES[i % TONES.length]} {...s} />
))}
</div>
<span className="w-rails" />
@ -335,8 +346,8 @@ export default function WebSite() {
<SectionHead index="04" label="drawer" title="Eighteen drives, all labelled" />
</Reveal>
<Reveal delay={60}>
<div className="w-mt-metal w-drawer">
<div className="w-mt-plastic w-drawer__inner w-scroll">
<div className="w-chassis w-drawer">
<div className="w-well w-drawer__inner w-scroll">
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
{codingProjects.map((p, i) => {
const { name, status } = splitStatus(p.title);
@ -347,7 +358,12 @@ export default function WebSite() {
target="_blank"
rel="noopener noreferrer"
className="w-drive"
style={{ "--tilt": `${i % 2 ? 0.5 : -0.6}deg` } as CSSProperties}
style={
{
"--tilt": `${i % 2 ? 0.6 : -0.7}deg`,
"--tone": TONES[i % TONES.length],
} as CSSProperties
}
title={p.desc}
>
<span className="w-drive__port" aria-hidden="true" />
@ -364,7 +380,7 @@ export default function WebSite() {
})}
</div>
</div>
<div className="w-mt-metal-flush w-drawer__front">
<div className="w-chassis-2 w-drawer__front">
<i className="w-screw" aria-hidden="true" />
<span className="w-drawer__handle" aria-hidden="true" />
<i className="w-screw" aria-hidden="true" />
@ -376,18 +392,22 @@ export default function WebSite() {
{/* ------------------------------------------------------ hardware */}
<section id="hardware" className="scroll-mt-28">
<Reveal>
<SectionHead index="05" label="machines" title="Tagged on the pegboard" />
<SectionHead index="05" label="machines" title="Pinned to the cork board" />
</Reveal>
<Reveal delay={60}>
<div className="w-mt-metal w-pegboard">
<div className="w-pegboard">
<div className="w-pegboard__face">
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
{techProjects.map((t) => (
<article key={t.title} className="w-mt-paper w-hangtag">
<span className="w-hangtag__clip" aria-hidden="true" />
<h3 className="w-display text-[1rem] text-[var(--ink)]">{t.title}</h3>
<p className="w-prose mb-4 mt-2 text-[0.8rem] text-[var(--ink-soft)]">{t.desc}</p>
<span className="w-barcode w-hangtag__bar" aria-hidden="true" />
<div className="grid gap-5 sm:grid-cols-2 xl:grid-cols-3">
{techProjects.map((t, i) => (
<article
key={t.title}
className="w-paper w-hangtag"
style={{ "--tone": TONES[i % TONES.length] } as CSSProperties}
>
<span className="w-pin" aria-hidden="true" />
<h3 className="w-display text-[1.05rem] text-[var(--ink)]">{t.title}</h3>
<span className="w-hangtag__rule" aria-hidden="true" />
<p className="w-prose text-[0.84rem] text-[var(--ink-soft)]">{t.desc}</p>
</article>
))}
</div>
@ -399,7 +419,7 @@ export default function WebSite() {
{/* -------------------------------------------------- activity feed */}
<section id="gitdxd" className="scroll-mt-28">
<Reveal>
<SectionHead index="06" label="gitdxd" title="The printer spits out the forge" />
<SectionHead index="06" label="gitdxd" title="The receipt for this year's commits" />
</Reveal>
<Reveal delay={60}>
<Report />
@ -418,11 +438,16 @@ export default function WebSite() {
href={f.realUrl || f.url}
target="_blank"
rel="noopener noreferrer"
className="w-mt-paper w-bizcard"
style={{ "--tilt": `${i === 1 ? 0.9 : i === 2 ? -1 : -1.4}deg` } as CSSProperties}
className="w-bizcard"
style={
{
"--tilt": `${i === 1 ? 0.9 : i === 2 ? -1 : -1.4}deg`,
"--tone": TONES[(i + 1) % TONES.length],
} as CSSProperties
}
>
<p className="w-serif text-[1.15rem] text-[var(--ink)]">{f.name}</p>
<p className="w-mono mt-1 text-[0.66rem] text-[var(--ink-soft)]">{f.desc}</p>
<p className="w-serif text-[1.2rem] text-[var(--ink)]">{f.name}</p>
<p className="w-mono mt-1 text-[0.68rem] text-[var(--ink-soft)]">{f.desc}</p>
</a>
</Reveal>
))}
@ -432,29 +457,32 @@ export default function WebSite() {
{/* ----------------------------------------------------------- gym */}
<section id="gym" className="scroll-mt-28">
<Reveal>
<SectionHead index="08" label="strength" title="Numbers on the clipboard" />
<SectionHead index="08" label="strength" title="Numbers on the scoreboard" />
</Reveal>
<Reveal delay={60}>
<div className="w-clipboard">
<div className="w-mt-metal w-clipboard__clip" aria-hidden="true" />
<div className="w-mt-paper w-logsheet">
<div className="w-sheet__head">
<span>training log</span>
<span className="ml-auto">73 kg bodyweight</span>
</div>
<div className="mt-3">
{LIFTS.map((l) => (
<div key={l.lift} className="w-logrow">
<span className="w-logrow__lift">{l.lift}</span>
<span className="w-logrow__weight">{l.weight} kg</span>
<span className="w-logrow__date">{l.date}</span>
</div>
))}
</div>
<p className="w-mono mt-4 text-[0.62rem] tracking-[0.14em] text-[var(--ink-soft)]">
BEST SBD TOTAL · 401 KG · 165 + 111 + 125
</p>
<div className="w-chassis w-score">
<div className="w-score__head">
<Led kind="on" pulse slow />
<span>TRAINING LOG · 73 KG BODYWEIGHT</span>
<span className="ml-auto hidden sm:inline">3 LIFTS</span>
</div>
<div className="w-score__tiles">
{LIFTS.map((l, i) => (
<div
key={l.lift}
className="w-score__tile"
style={{ "--tone": TONES[(i + 2) % TONES.length] } as CSSProperties}
>
<span className="w-score__num">
{l.weight}
<small>kg</small>
</span>
<span className="w-score__lift">{l.lift}</span>
<span className="w-score__date">{l.date}</span>
</div>
))}
</div>
<p className="w-score__foot">BEST SBD TOTAL · 401 KG · 165 + 111 + 125</p>
</div>
</Reveal>
</section>
@ -465,16 +493,23 @@ export default function WebSite() {
<SectionHead index="09" label="patch panel" title="Twelve ports, all live" />
</Reveal>
<Reveal delay={60}>
<div className="w-mt-metal w-patch">
<div className="w-mt-metal-flush w-patch__face">
<div className="w-chassis w-patch">
<div className="w-chassis-2 w-patch__face">
<div className="w-patch__head">
<i className="w-screw" aria-hidden="true" />
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">PATCH 01 · SOCIALS</span>
<span>PATCH 01 · SOCIALS</span>
<i className="w-screw ml-auto" aria-hidden="true" />
</div>
<div className="grid gap-2.5 sm:grid-cols-2 xl:grid-cols-3">
{socials.map((s) => (
<a key={s.name} href={s.url} target="_blank" rel="noopener noreferrer" className="w-port">
{socials.map((s, i) => (
<a
key={s.name}
href={s.url}
target="_blank"
rel="noopener noreferrer"
className="w-port"
style={{ "--tone": TONES[i % TONES.length] } as CSSProperties}
>
<span className="w-port__jack" aria-hidden="true">
<span className="w-port__slot" />
</span>
@ -485,7 +520,7 @@ export default function WebSite() {
</a>
))}
</div>
<p className="w-mono mt-5 text-[0.64rem] tracking-[0.06em] text-[var(--ftext-faint)]">
<p className="w-mono mt-5 text-[0.66rem] text-[var(--chassis-faint)]">
fastest reply is Discord or Instagram · mail{" "}
<a className="w-link" href="mailto:dvorak@dvorakmortonxd.dev">
dvorak@dvorakmortonxd.dev
@ -501,11 +536,13 @@ export default function WebSite() {
{/* ------------------------------------------------------------ footer */}
<footer className="mx-auto w-full max-w-[1120px] px-5 pb-16 sm:px-8">
<Reveal>
<div className="w-mt-alu relative flex flex-col gap-5 px-6 py-5 sm:flex-row sm:items-center sm:justify-between">
<div className="w-plastic relative flex flex-col gap-5 px-6 py-5 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<p className="w-mono text-[0.72rem] tracking-[0.2em]">DVORAKMORTONXD.LOCAL</p>
<p className="w-mono mt-1.5 text-[0.62rem] opacity-80">
v3.3.0 · GPL-3.0-only · built with Next.js · textures CC0 via{" "}
<p className="w-display text-[0.8rem] tracking-[0.16em] text-[var(--plastic-ink)]">
DVORAKMORTONXD.LOCAL
</p>
<p className="w-mono mt-1.5 text-[0.64rem] text-[var(--ink-soft)]">
v4.0.0 · GPL-3.0-only · built with Next.js · no textures, all CSS ·{" "}
<a className="w-link" href="/credits">
credits
</a>
@ -514,15 +551,15 @@ export default function WebSite() {
<button
type="button"
onClick={() => setTheme("skeuo")}
className="w-keybtn desktop-toggle shrink-0 self-start sm:self-auto"
className="w-keybtn w-btn-accent desktop-toggle shrink-0 self-start sm:self-auto"
title="Flip to Desktop mode"
>
<Led kind="amber" /> desktop mode
<Led kind="on" /> desktop mode
</button>
<i className="w-screw w-screw--alu w-corner-tr" aria-hidden="true" />
<i className="w-screw w-screw--alu w-corner-bl" aria-hidden="true" />
<i className="w-screw w-corner-tr" aria-hidden="true" />
<i className="w-screw w-corner-bl" aria-hidden="true" />
</div>
<p className="w-mono mt-4 text-[0.62rem] text-[var(--ftext-faint)]">
<p className="w-mono mt-4 text-[0.64rem] text-[var(--ink-soft)]">
© 2025–2026 Martin Dvořák — follow the licence or don&rsquo;t, I don&rsquo;t mind
</p>
</Reveal>

View file

@ -79,22 +79,34 @@ export function Led({
);
}
export function Screws({ count = 2, alu = false, className = "" }: { count?: number; alu?: boolean; className?: string }) {
export function Screws({ count = 2, className = "" }: { count?: number; className?: string }) {
return (
<span className={`w-unit__screws ${className}`}>
{Array.from({ length: count }).map((_, i) => (
<i key={i} className={`w-screw${alu ? " w-screw--alu" : ""}`} />
<i key={i} className="w-screw" />
))}
</span>
);
}
/** Section heading: an etched aluminium tab on the desk + painted title. */
/** Section heading: a coloured chip on the desk + a painted title. */
export function SectionHead({ index, label, title }: { index: string; label: string; title: string }) {
const tones = [
"var(--orange)",
"var(--teal)",
"var(--blue)",
"var(--lilac)",
"var(--mint)",
"var(--coral)",
"var(--yellow)",
];
const n = Number.parseInt(index, 10);
const tone = tones[Number.isFinite(n) ? (n - 1) % tones.length : 0];
return (
<div className="w-sechead">
<span className="w-mt-alu w-sechead__tab">
<b>{index}</b> {label}
<span className="w-chip w-sechead__tab" style={{ "--tone": tone } as CSSProperties}>
{index} · {label}
</span>
<h2 className="w-display w-paint w-sechead__title">{title}</h2>
</div>
@ -107,9 +119,9 @@ export function Monitor({ children, className = "" }: { children: ReactNode; cla
return (
<div className={`w-monitor ${className}`}>
<div className="w-monitor__frame">
<div className="w-mt-glass w-monitor__glass">{children}</div>
<div className="w-glass w-monitor__glass">{children}</div>
<div className="w-monitor__chin">
<Led kind="amber" />
<Led kind="on" />
<span className="w-monitor__brand">DXD</span>
<span className="w-monitor__osd" aria-hidden="true">
<i className="w-osdkey" />
@ -127,6 +139,7 @@ export function Monitor({ children, className = "" }: { children: ReactNode; cla
}
const KEY_ROWS = ["1234567890-=".split(""), "qwertyuiop[]".split(""), "asdfghjkl;'".split("")];
const CAP_TONES = ["var(--mint)", "var(--blue)", "var(--yellow)", "var(--coral)", "var(--lilac)", "var(--teal)"];
export function Keyboard() {
return (
@ -134,16 +147,20 @@ export function Keyboard() {
<div className="w-keyboard__deck">
<div className="w-keyboard__row">
<span className="w-key w-key--accent">esc</span>
{KEY_ROWS[0].map((k) => (
<span key={k} className="w-key">
{KEY_ROWS[0].map((k, i) => (
<span key={k} className="w-key" style={{ "--tone": CAP_TONES[i % CAP_TONES.length] } as CSSProperties}>
{k}
</span>
))}
</div>
{KEY_ROWS.slice(1).map((row, i) => (
<div key={i} className="w-keyboard__row">
{row.map((k) => (
<span key={k} className="w-key">
{KEY_ROWS.slice(1).map((row, r) => (
<div key={r} className="w-keyboard__row">
{row.map((k, i) => (
<span
key={k}
className="w-key"
style={{ "--tone": CAP_TONES[(i + r + 2) % CAP_TONES.length] } as CSSProperties}
>
{k}
</span>
))}
@ -158,24 +175,27 @@ export function Keyboard() {
);
}
const RACK_TONES = ["var(--mint)", "var(--blue)", "var(--yellow)", "var(--coral)"];
/** A small rack that sits on the desk in the hero. */
export function MiniRack({ label = "DXD-01" }: { label?: string }) {
return (
<div className="w-rack w-mt-metal" aria-hidden="true">
<div className="w-chassis w-rack" aria-hidden="true">
<div className="w-rack__top">
<Led kind="on" pulse />
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">{label}</span>
<span className="w-display text-[0.68rem] tracking-[0.2em] text-[var(--chassis-ink)]">{label}</span>
<span className="w-rack__vent w-vents" />
</div>
<div className="w-rack__grid">
<span className="w-rails" />
<div>
{[0, 1, 2, 3].map((i) => (
<div key={i} className="w-unit !min-h-[46px] !gap-[10px] !py-2">
<span className="w-unit__grille !h-6 !w-9" />
<div key={i} className="w-unit !min-h-[48px] !gap-[10px] !py-2" style={{ "--tone": RACK_TONES[i] } as CSSProperties}>
<span className="w-unit__grip !h-7 !w-3" />
<span className="w-unit__grille !h-7 !w-10" />
<Led kind="on" pulse style={{ animationDelay: `${i * 0.5}s` }} />
<Led kind="amber" pulse slow style={{ animationDelay: `${i * 0.3}s` }} />
<span className="ml-auto w-engrave text-[0.58rem] tracking-[0.14em]">
<span className="w-display ml-auto text-[0.6rem] tracking-[0.14em] text-[var(--chassis-dim)]">
{["pxe", "aio", "nas", "web"][i]}
</span>
</div>
@ -187,13 +207,13 @@ export function MiniRack({ label = "DXD-01" }: { label?: string }) {
);
}
/** A machined aluminium plate with one number etched into it. */
export function Plaque({ value, label }: { value: string; label: string }) {
/** A big coloured sticker with one number on it. */
export function Plaque({ value, label, tone = "var(--orange)" }: { value: string; label: string; tone?: string }) {
return (
<div className="w-mt-alu w-plaque">
<div className="w-sticker w-plaque" style={{ "--tone": tone } as CSSProperties}>
<span className="w-plaque__value">{value}</span>
<span className="w-plaque__label">{label}</span>
<Led kind="amber" className="w-plaque__dot" />
<i className="w-plaque__dot" aria-hidden="true" />
</div>
);
}
@ -209,6 +229,7 @@ export function ServiceUnit({
access,
checkUrl,
disabled,
tone = "var(--teal)",
}: {
name: string;
desc: string;
@ -216,6 +237,7 @@ export function ServiceUnit({
access?: ServiceAccess;
checkUrl?: string;
disabled?: boolean;
tone?: string;
}) {
const [status, setStatus] = useState<"pending" | "up" | "down">("pending");
@ -237,6 +259,7 @@ export function ServiceUnit({
const live = disabled ? "up" : status;
const kind = live === "up" ? "on" : live === "down" ? "off" : "amber";
const stateClass = disabled ? "is-wait" : live === "up" ? "is-on" : live === "down" ? "is-off" : "is-wait";
const label = disabled ? "STANDBY" : live === "up" ? "ONLINE" : live === "down" ? "OFFLINE" : "POLLING";
const accessLabel = access === "public" ? "public" : access === "private" ? "private" : access === "on_request" ? "on request" : null;
@ -253,8 +276,8 @@ export function ServiceUnit({
<span className="w-unit__grip" aria-hidden="true" />
<span className="w-unit__grille w-grille" aria-hidden="true" />
<span className="w-unit__id">
<span className="w-unit__name w-engrave">{name}</span>
<span className="w-tape mt-1">
<span className="w-unit__name">{name}</span>
<span className="w-tape mt-1.5">
{host}
{accessLabel ? ` · ${accessLabel}` : ""}
</span>
@ -262,7 +285,7 @@ export function ServiceUnit({
</span>
<span className="w-unit__state">
<Led kind={kind} pulse={live === "up"} />
<span className="w-unit__status w-engrave">{label}</span>
<span className={`w-unit__status ${stateClass}`}>{label}</span>
</span>
<Screws />
</>
@ -270,13 +293,20 @@ export function ServiceUnit({
if (disabled) {
return (
<span className="w-unit" aria-disabled="true">
<span className="w-unit" style={{ "--tone": tone } as CSSProperties} aria-disabled="true">
{inner}
</span>
);
}
return (
<a href={url} target="_blank" rel="noopener noreferrer" className="w-unit w-unit--link" title={desc}>
<a
href={url}
target="_blank"
rel="noopener noreferrer"
className="w-unit w-unit--link"
style={{ "--tone": tone } as CSSProperties}
title={desc}
>
{inner}
</a>
);
@ -295,7 +325,7 @@ interface Activity {
repo?: { full_name?: string };
}
const DOT_OPACITY = [0.07, 0.3, 0.48, 0.64, 0.82];
const DOT_OPACITY = [0.12, 0.35, 0.55, 0.75, 1];
export function Report() {
const [weeks, setWeeks] = useState<{ date: string; contribs: number; level: number }[][]>([]);
@ -377,7 +407,7 @@ export function Report() {
return (
<div className="w-printout">
<div className="w-mt-paper w-printout__paper">
<div className="w-printout__paper">
<p className="w-print__head">
<span>GITDXD · ACTIVITY REPORT · 12 MONTHS</span>
<span className="ml-auto flex items-center gap-3">
@ -387,20 +417,20 @@ export function Report() {
</p>
{state === "error" ? (
<p className="w-mono mt-5 text-[0.72rem] text-[#4a4133]">could not reach the forge.</p>
<p className="w-mono mt-5 text-[0.74rem] text-[var(--ink-soft)]">could not reach the forge.</p>
) : (
<>
<div className="mt-5 flex flex-wrap items-end gap-x-6 gap-y-2">
<div>
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[#4a4133]">TOTAL / 12 MONTHS</p>
<p className="w-display text-[2.6rem] leading-none text-[var(--ink)]">
<p className="w-kicker">total / 12 months</p>
<p className="w-display mt-1 text-[2.6rem] leading-none text-[var(--ink)]">
{state === "loading" ? "—" : total}
</p>
</div>
<p className="w-mono text-[0.62rem] leading-relaxed text-[#6f6450]">
each dot = one day
<p className="w-mono text-[0.64rem] leading-relaxed text-[var(--ink-soft)]">
each square = one day
<br />
darkest = busiest
strongest orange = busiest
</p>
</div>