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:
parent
a71cfb1731
commit
1880a5b0db
14 changed files with 1165 additions and 989 deletions
|
|
@ -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’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)]">
|
||||
“If it has a fan, I’ll find a use for it.”
|
||||
</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’m hosting an SMP — message me on Discord if you want in. I’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’t, I don’t mind
|
||||
</p>
|
||||
</Reveal>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,34 +4,32 @@ import "../web.css";
|
|||
|
||||
export const metadata: Metadata = {
|
||||
title: "credits · dvorakmortonxd.dev",
|
||||
description: "Textures, type and other borrowed work used on dvorakmortonxd.dev.",
|
||||
description: "Type and other borrowed work used on dvorakmortonxd.dev.",
|
||||
};
|
||||
|
||||
const TEXTURES = [
|
||||
{ file: "desk.jpg", asset: "Wood 028", id: "Wood028", use: "the near-black desk" },
|
||||
{ file: "metal.jpg", asset: "Metal 051 C", id: "Metal051C", use: "rack, monitor, panel hardware" },
|
||||
{ file: "paper.jpg", asset: "Paper 003", id: "Paper003", use: "sheets, labels, tape, the report" },
|
||||
{ file: "carbon.jpg", asset: "Fabric 004", id: "Fabric004", use: "the keyboard deck" },
|
||||
{ file: "plastic.jpg", asset: "Plastic 012 A", id: "Plastic012A", use: "the drawer interior" },
|
||||
];
|
||||
|
||||
const FONTS = [
|
||||
{
|
||||
name: "Nunito",
|
||||
by: "Vernon Adams, Cyreal, Jacques Le Bailly",
|
||||
use: "hardware labels, headings, buttons",
|
||||
href: "https://fonts.google.com/specimen/Nunito",
|
||||
},
|
||||
{
|
||||
name: "Newsreader",
|
||||
by: "Production Type",
|
||||
use: "printed headlines, sheet copy, stamped numbers",
|
||||
use: "anything printed on paper",
|
||||
href: "https://fonts.google.com/specimen/Newsreader",
|
||||
},
|
||||
{
|
||||
name: "IBM Plex Sans",
|
||||
by: "IBM",
|
||||
use: "body text on the desk",
|
||||
use: "body copy",
|
||||
href: "https://fonts.google.com/specimen/IBM+Plex+Sans",
|
||||
},
|
||||
{
|
||||
name: "IBM Plex Mono",
|
||||
by: "IBM",
|
||||
use: "engraved labels, terminal text, index cards",
|
||||
use: "terminal text, receipt, technical labels",
|
||||
href: "https://fonts.google.com/specimen/IBM+Plex+Mono",
|
||||
},
|
||||
];
|
||||
|
|
@ -41,70 +39,34 @@ export default function Credits() {
|
|||
<div className="w-page">
|
||||
<main className="mx-auto w-full max-w-[1120px] px-5 pt-24 pb-20 sm:px-8">
|
||||
<div className="w-sechead">
|
||||
<span className="w-mt-alu w-sechead__tab">credits</span>
|
||||
<span className="w-chip w-sechead__tab" style={{ "--tone": "var(--mint)" } as React.CSSProperties}>
|
||||
credits
|
||||
</span>
|
||||
<h1 className="w-display w-paint w-sechead__title">Everything borrowed, credited.</h1>
|
||||
</div>
|
||||
<p className="w-prose w-paint max-w-[64ch] text-[var(--ftext-dim)]">
|
||||
The desk is built out of five CC0 textures and three open-licensed typefaces. Nothing is scraped
|
||||
or unlicensed — the authors are named even where the licence does not require it.
|
||||
<p className="w-prose w-paint max-w-[62ch] text-[var(--ink-soft)]">
|
||||
The desk contains <strong>no images at all</strong> — every surface, screw, LED, paper sheet and coffee
|
||||
mug is drawn in CSS. That means there are no photography or texture licences to track: the only
|
||||
borrowed work is type.
|
||||
</p>
|
||||
|
||||
<section className="mt-14">
|
||||
<div className="w-sechead !mb-6">
|
||||
<span className="w-mt-alu w-sechead__tab">textures</span>
|
||||
<h2 className="w-display w-paint w-sechead__title !text-[1.3rem]">ambientCG — CC0 1.0</h2>
|
||||
</div>
|
||||
<p className="w-prose w-paint max-w-[64ch] text-[var(--ftext-dim)]">
|
||||
All five materials come from{" "}
|
||||
<a className="w-link" href="https://ambientcg.com" target="_blank" rel="noopener noreferrer">
|
||||
ambientCG
|
||||
</a>{" "}
|
||||
(Struffel Productions) under the{" "}
|
||||
<a
|
||||
className="w-link"
|
||||
href="https://creativecommons.org/publicdomain/zero/1.0/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
CC0 1.0
|
||||
</a>{" "}
|
||||
public-domain dedication. I downloaded the 1K JPG colour maps, downscaled them to 512 px and
|
||||
tint them in CSS.
|
||||
</p>
|
||||
|
||||
<ul className="mt-7 grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
|
||||
{TEXTURES.map((t) => (
|
||||
<li key={t.id} className="w-mt-paper w-cardindex">
|
||||
<p className="w-serif text-[1.05rem] text-[var(--ink)]">{t.asset}</p>
|
||||
<p className="w-mono mt-2 text-[0.64rem] leading-relaxed text-[var(--ink-soft)]">
|
||||
source:{" "}
|
||||
<a
|
||||
className="w-link"
|
||||
href={`https://ambientcg.com/view?id=${t.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
ambientCG / {t.id}
|
||||
</a>
|
||||
<br />
|
||||
licence: CC0 1.0
|
||||
<br />
|
||||
used as <code>{`/textures/${t.file}`}</code> — {t.use}
|
||||
</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="mt-16">
|
||||
<div className="w-sechead !mb-6">
|
||||
<span className="w-mt-alu w-sechead__tab">type</span>
|
||||
<h2 className="w-display w-paint w-sechead__title !text-[1.3rem]">Google Fonts — SIL OFL 1.1</h2>
|
||||
<span className="w-chip w-sechead__tab" style={{ "--tone": "var(--teal)" } as React.CSSProperties}>
|
||||
type
|
||||
</span>
|
||||
<h2 className="w-display w-paint w-sechead__title !text-[1.3rem]">
|
||||
Google Fonts — SIL Open Font License 1.1
|
||||
</h2>
|
||||
</div>
|
||||
<ul className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
|
||||
{FONTS.map((f) => (
|
||||
<li key={f.name} className="w-mt-paper w-cardindex w-cardindex--alt">
|
||||
<p className="w-serif text-[1.05rem] text-[var(--ink)]">{f.name}</p>
|
||||
<ul className="grid gap-5 sm:grid-cols-2 xl:grid-cols-4">
|
||||
{FONTS.map((f, i) => (
|
||||
<li
|
||||
key={f.name}
|
||||
className="w-paper w-cardindex"
|
||||
style={{ "--tone": ["var(--orange)", "var(--blue)", "var(--lilac)", "var(--mint)"][i % 4] } as React.CSSProperties}
|
||||
>
|
||||
<p className="w-display text-[1.05rem] text-[var(--ink)]">{f.name}</p>
|
||||
<p className="w-mono mt-2 text-[0.64rem] leading-relaxed text-[var(--ink-soft)]">
|
||||
by {f.by}
|
||||
<br />
|
||||
|
|
@ -122,13 +84,15 @@ export default function Credits() {
|
|||
|
||||
<section className="mt-16">
|
||||
<div className="w-sechead !mb-6">
|
||||
<span className="w-mt-alu w-sechead__tab">notes</span>
|
||||
<span className="w-chip w-sechead__tab" style={{ "--tone": "var(--lilac)" } as React.CSSProperties}>
|
||||
notes
|
||||
</span>
|
||||
<h2 className="w-display w-paint w-sechead__title !text-[1.3rem]">Other marks</h2>
|
||||
</div>
|
||||
<p className="w-prose w-paint max-w-[64ch] text-[var(--ftext-dim)]">
|
||||
The social ports use brand marks that remain the property of their owners and are used only to
|
||||
link to those accounts. Everything written on the paper is mine. The desktop mode (the KDE
|
||||
simulation) uses its own separate assets.
|
||||
<p className="w-prose w-paint max-w-[62ch] text-[var(--ink-soft)]">
|
||||
The patch panel uses brand marks that remain the property of their owners and are used only to
|
||||
link to those accounts. Everything written on the paper — and every pixel of the desk itself — is
|
||||
mine. The desktop mode (the KDE simulation) uses its own separate assets.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -37,15 +37,20 @@
|
|||
--ease-cinematic: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
/* Beats page.css's :root when the editorial theme is active. */
|
||||
/* Beats page.css's :root when the web theme is active. The desk is a light,
|
||||
colourful, cartoon-skeuomorphic surface — the dark gruvbox values in :root
|
||||
are only the fallback for the desktop mode. */
|
||||
html[data-theme="web"] {
|
||||
color-scheme: dark;
|
||||
--accent: #fe8019;
|
||||
--accent2: #d65d0e;
|
||||
--accent3: #fabd2f;
|
||||
--green: #b8bb26;
|
||||
--red: #fb4934;
|
||||
--gray: #a89984;
|
||||
color-scheme: light;
|
||||
--bg: #f7e7c6;
|
||||
--bg-raised: #fffdf6;
|
||||
--bg-well: #eed9b0;
|
||||
--accent: #f4823a;
|
||||
--accent2: #d4611c;
|
||||
--accent3: #f2c14e;
|
||||
--green: #58bd72;
|
||||
--red: #ea6f6a;
|
||||
--gray: #7f7768;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
|
|
@ -71,7 +76,7 @@ html[data-theme="web"] {
|
|||
}
|
||||
|
||||
html[data-theme="web"] ::selection {
|
||||
background: rgba(254, 128, 25, 0.28);
|
||||
background: rgba(244, 130, 58, 0.3);
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
|
|
@ -88,12 +93,12 @@ html[data-theme="web"] ::-webkit-scrollbar-track {
|
|||
background: var(--bg-well);
|
||||
}
|
||||
html[data-theme="web"] ::-webkit-scrollbar-thumb {
|
||||
background: #3c3836;
|
||||
background: #d9c49b;
|
||||
border: 3px solid var(--bg-well);
|
||||
border-radius: 99px;
|
||||
}
|
||||
html[data-theme="web"] ::-webkit-scrollbar-thumb:hover {
|
||||
background: #504945;
|
||||
background: #c9b184;
|
||||
}
|
||||
|
||||
/* Phones never get the desktop-mode button. */
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type { Metadata } from "next";
|
||||
import { Newsreader, IBM_Plex_Sans, IBM_Plex_Mono } from "next/font/google";
|
||||
import { Newsreader, IBM_Plex_Sans, IBM_Plex_Mono, Nunito } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import ThemeScript from "./components/ThemeScript";
|
||||
|
||||
// Display serif for headlines, Plex for body/labels — same pairing as the
|
||||
// reference editorial site.
|
||||
// The web desk pairs a rounded sans (hardware labels, headings) with a printed
|
||||
// serif (anything on paper) and a mono (terminal text + technical labels).
|
||||
const news = Newsreader({
|
||||
variable: "--font-news",
|
||||
subsets: ["latin"],
|
||||
|
|
@ -24,6 +24,12 @@ const plexMono = IBM_Plex_Mono({
|
|||
weight: ["400", "500"],
|
||||
display: "swap",
|
||||
});
|
||||
const round = Nunito({
|
||||
variable: "--font-round",
|
||||
subsets: ["latin"],
|
||||
weight: ["600", "700", "800"],
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "dvorakmortonxd.dev",
|
||||
|
|
@ -51,7 +57,7 @@ export default function RootLayout({
|
|||
lang="en"
|
||||
data-theme="web"
|
||||
suppressHydrationWarning
|
||||
className={`${news.variable} ${plex.variable} ${plexMono.variable}`}
|
||||
className={`${news.variable} ${plex.variable} ${plexMono.variable} ${round.variable}`}
|
||||
>
|
||||
<body className="antialiased">
|
||||
<noscript>
|
||||
|
|
|
|||
1614
src/app/web.css
1614
src/app/web.css
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue