diff --git a/README.md b/README.md index 1a96764..fbeb7a7 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ from the saved theme, all from the same content: - **`web`** (default) — a light, frosted-glass **website**: a sticky full-height sidebar (section nav, light/dark switch, desktop switch) beside a column of glass cards — hero with - a socials row, quick tiles, the Revival Inc. / RustyWolf feature panels (drawn as little - CSS windows, not screenshots), live services, - activity heatmap, projects and hardware (a masonry gallery), and friends. Dark by default + a socials row, quick tiles, the Freezmo feature panel (a real app screenshot) above the + Revival Inc. / RustyWolf CSS mock windows, live services, + activity heatmap, projects and hardware (grouped index lists), and friends. Dark by default with a persisted light mode, and fully responsive, so phones and desktops get the same shell. - **`skeuo`** — an alternate KDE Plasma / Windows-style **desktop simulation** (desktop only): draggable snap-to-grid icons, resizable/floating windows, a Start menu, taskbar and @@ -36,11 +36,12 @@ more. hand-built CSS mock windows instead of screenshots: a little necromancy game scene whose blinking "PRESS START" launches the game, and a little browser window with tabs in the title bar, a toolbar and a start page. -- **Asset-free cards & wallpaper** — every project/hardware card is a CSS gradient tile with - an emoji glyph (no screenshots), the desktop shell's app previews are the same CSS mock +- **Asset-free index & wallpaper** — Projects and Hardware are grouped repo-style index lists + (category headers, status/language chips, language-tinted dots on project rows, years — no emoji, no + screenshots), the desktop shell's app previews are the same CSS mock windows (a git-forge page for GitDXD), and its wallpaper is a layered CSS gradient. The - only real images left are the logo, the social SVGs, the Joker easter egg and the Gentoo - mark. + only real images left are the logo, the social SVGs, the Freezmo screenshot, the Joker + easter egg and the Gentoo mark. - **Draggable desktop icons** — free placement that snaps to a measured grid, one icon per cell, with a follow-the-cursor drag ghost. Icons shrink on cramped viewports so they never collide. diff --git a/agents.md b/agents.md index 7b057ce..dc408d5 100644 --- a/agents.md +++ b/agents.md @@ -157,15 +157,25 @@ Themes: `web` = default frosted-glass website (sidebar + content, light/dark), rectangle/square and never ends in an orphan "L" row (a 4th friend made the old 3-column grid do that). The same `friend.emoji` drives the desktop friend icon (Josef is 🧌 goblin, the rest 🧙 — the old per-friend SVGs are gone). - Projects/hardware use a CSS multi-column - **masonry** gallery (`.project-grid`) so short cards don't leave half-empty - grid slots; on phones it drops to 2 columns with a shorter tile. Cards are - **asset-free**: each renders a `.project-thumb` — a `.thumb-N` gradient - (N = index % 6) with the item's `emoji` glyph centred — instead of a - screenshot. `codingProjects` / `techProjects` in `data.ts` carry `emoji` - (no `img`/`image`). The two feature panels (`.web-split`) stretch + Projects/hardware render as a grouped repo-listing-style + **index** (`ProjectIndex.tsx`, `.index-*` classes): group headers + (Games & game jams / Linux & desktop / Bots, servers & plugins / Apps & + experiments; Desktops & servers / Laptops / Phones / Consoles & handhelds), + then rows: coding rows lead with a language-coloured dot, title and a + status pill over the description, with the language/host tag right-aligned; + hardware rows are plain (no dot) with the year right-aligned. Coding rows are + external links with a hover highlight + arrow; hardware rows are static. The + rows are **asset-free** (no emoji, no screenshots). `codingProjects` in + `data.ts` carries `slug` / `group` / `status?` / `tag` / `accent`; + `techProjects` carries `slug` / `group` / `year?` + (no `img`/`image`/`emoji`/`accent`). Status pill colors come from the `--status-*` + tokens in `web.css`, overridden for the dark desktop windows in `skeuo.css` + along with the row hairlines (`--index-line`). Above the split, the full-width + **Freezmo** feature panel (`.web-feature` + `.web-feature-shot`) is the one + place a **real screenshot** is used (`public/freezmo-app.webp`, the live + study app). The two remaining feature panels (`.web-split`) stretch to equal height and share a fixed `16 / 10` `.fw` window (the `FeatureWindow` - component) — a decorative, **asset-free CSS mock-up** rather than a screenshot: + component) — decorative, **asset-free CSS mock-ups** rather than screenshots: Revival Inc. is a little necromancy game scene (night sky, moon, tombstones, blinking "PRESS START") and RustyWolf is a little browser window (tabs in the title bar, toolbar, address bar, start page). The browser window is `aria-hidden` @@ -178,11 +188,13 @@ Themes: `web` = default frosted-glass website (sidebar + content, light/dark), Revival Inc. → game, RustyWolf → browser), so there are no app-preview screenshots. The old stacked TUI panel layout and the `SlBackground` ASCII train were removed earlier. -- **No raster UI assets.** Every card, feature panel, app preview and the desktop - wallpaper is drawn in CSS: project/hardware cards are `.project-thumb` gradient - tiles with an `emoji`, the feature/app previews are `FeatureWindow` mock windows, +- **No raster UI assets.** Every list, feature panel mock, app preview and the + desktop wallpaper is drawn in CSS: project/hardware entries are `.index-row` + list rows (accent dot, status pill, tag/year, hairline separators), the + feature/app previews are `FeatureWindow` mock windows, and `.win-desktop` carries a layered gradient "wallpaper" (there is no - `wallpaper.jpg`). Only the social SVGs, the site logo (`src/app/icon.png`), the + `wallpaper.jpg`). Only the social SVGs, the site logo (`src/app/icon.png`), + the Freezmo screenshot (`public/freezmo-app.webp`), the Joker easter egg (`joker.webp`) and the Gentoo mark (`gentoo.svg`) remain as real image files. - **Not a terminal.** The web theme deliberately has no TUI chrome: the hero is @@ -207,7 +219,8 @@ Themes: `web` = default frosted-glass website (sidebar + content, light/dark), alphas makes dark look far more gradient-heavy. Tune the two schemes separately, not by eye against each other. - Interactive surfaces (`.web-ctl`, `.service-button`, `.social-button`, - `.project-card`, `.gym-item`, `.contribution-entry`, `.heatmap-container`) read + `.index-list`, `a.index-row:hover`, `.gym-item`, `.contribution-entry`, + `.heatmap-container`) read the `--btn-bg` / `--btn-bg-hi` / `--btn-border` / `--btn-shadow` tokens with the glass tokens as **fallbacks** (`var(--btn-bg, var(--glass-lo))`). The tokens are only defined under `html[data-theme="web"]`, so the desktop theme diff --git a/package-lock.json b/package-lock.json index e30b5ad..1de9256 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1901,9 +1901,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", - "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz", + "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==", "cpu": [ "arm64" ], @@ -1919,13 +1919,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.3.3" + "@img/sharp-libvips-darwin-arm64": "1.3.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", - "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz", + "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==", "cpu": [ "x64" ], @@ -1941,20 +1941,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.3.3" + "@img/sharp-libvips-darwin-x64": "1.3.4" } }, "node_modules/@img/sharp-freebsd-wasm32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", - "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz", + "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==", "license": "Apache-2.0", "optional": true, "os": [ "freebsd" ], "dependencies": { - "@img/sharp-wasm32": "0.35.4" + "@img/sharp-wasm32": "0.35.5" }, "engines": { "node": ">=20.9.0" @@ -1964,9 +1964,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", - "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz", + "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==", "cpu": [ "arm64" ], @@ -1980,9 +1980,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", - "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz", + "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==", "cpu": [ "x64" ], @@ -1996,9 +1996,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", - "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz", + "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==", "cpu": [ "arm" ], @@ -2015,9 +2015,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", - "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz", + "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==", "cpu": [ "arm64" ], @@ -2034,9 +2034,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", - "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz", + "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==", "cpu": [ "ppc64" ], @@ -2053,9 +2053,9 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", - "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz", + "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==", "cpu": [ "riscv64" ], @@ -2072,9 +2072,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", - "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz", + "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==", "cpu": [ "s390x" ], @@ -2091,9 +2091,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", - "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz", + "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==", "cpu": [ "x64" ], @@ -2110,9 +2110,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", - "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz", + "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==", "cpu": [ "arm64" ], @@ -2129,9 +2129,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", - "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz", + "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==", "cpu": [ "x64" ], @@ -2148,9 +2148,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", - "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz", + "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==", "cpu": [ "arm" ], @@ -2169,13 +2169,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.3.3" + "@img/sharp-libvips-linux-arm": "1.3.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", - "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz", + "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==", "cpu": [ "arm64" ], @@ -2194,13 +2194,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.3.3" + "@img/sharp-libvips-linux-arm64": "1.3.4" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", - "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz", + "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==", "cpu": [ "ppc64" ], @@ -2219,13 +2219,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.3.3" + "@img/sharp-libvips-linux-ppc64": "1.3.4" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", - "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz", + "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==", "cpu": [ "riscv64" ], @@ -2244,13 +2244,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.3.3" + "@img/sharp-libvips-linux-riscv64": "1.3.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", - "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz", + "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==", "cpu": [ "s390x" ], @@ -2269,13 +2269,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.3.3" + "@img/sharp-libvips-linux-s390x": "1.3.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", - "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz", + "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==", "cpu": [ "x64" ], @@ -2294,13 +2294,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.3.3" + "@img/sharp-libvips-linux-x64": "1.3.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", - "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz", + "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==", "cpu": [ "arm64" ], @@ -2319,13 +2319,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", - "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz", + "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==", "cpu": [ "x64" ], @@ -2344,13 +2344,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.3.3" + "@img/sharp-libvips-linuxmusl-x64": "1.3.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", - "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz", + "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==", "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { @@ -2364,16 +2364,16 @@ } }, "node_modules/@img/sharp-webcontainers-wasm32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", - "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz", + "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==", "cpu": [ "wasm32" ], "license": "Apache-2.0", "optional": true, "dependencies": { - "@img/sharp-wasm32": "0.35.4" + "@img/sharp-wasm32": "0.35.5" }, "engines": { "node": ">=20.9.0" @@ -2383,9 +2383,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", - "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz", + "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==", "cpu": [ "arm64" ], @@ -2402,9 +2402,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", - "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz", + "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==", "cpu": [ "ia32" ], @@ -2421,9 +2421,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", - "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz", + "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==", "cpu": [ "x64" ], @@ -8052,9 +8052,9 @@ } }, "node_modules/sharp": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", - "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz", + "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -8069,31 +8069,31 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.35.4", - "@img/sharp-darwin-x64": "0.35.4", - "@img/sharp-freebsd-wasm32": "0.35.4", - "@img/sharp-libvips-darwin-arm64": "1.3.3", - "@img/sharp-libvips-darwin-x64": "1.3.3", - "@img/sharp-libvips-linux-arm": "1.3.3", - "@img/sharp-libvips-linux-arm64": "1.3.3", - "@img/sharp-libvips-linux-ppc64": "1.3.3", - "@img/sharp-libvips-linux-riscv64": "1.3.3", - "@img/sharp-libvips-linux-s390x": "1.3.3", - "@img/sharp-libvips-linux-x64": "1.3.3", - "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", - "@img/sharp-libvips-linuxmusl-x64": "1.3.3", - "@img/sharp-linux-arm": "0.35.4", - "@img/sharp-linux-arm64": "0.35.4", - "@img/sharp-linux-ppc64": "0.35.4", - "@img/sharp-linux-riscv64": "0.35.4", - "@img/sharp-linux-s390x": "0.35.4", - "@img/sharp-linux-x64": "0.35.4", - "@img/sharp-linuxmusl-arm64": "0.35.4", - "@img/sharp-linuxmusl-x64": "0.35.4", - "@img/sharp-webcontainers-wasm32": "0.35.4", - "@img/sharp-win32-arm64": "0.35.4", - "@img/sharp-win32-ia32": "0.35.4", - "@img/sharp-win32-x64": "0.35.4" + "@img/sharp-darwin-arm64": "0.35.5", + "@img/sharp-darwin-x64": "0.35.5", + "@img/sharp-freebsd-wasm32": "0.35.5", + "@img/sharp-libvips-darwin-arm64": "1.3.4", + "@img/sharp-libvips-darwin-x64": "1.3.4", + "@img/sharp-libvips-linux-arm": "1.3.4", + "@img/sharp-libvips-linux-arm64": "1.3.4", + "@img/sharp-libvips-linux-ppc64": "1.3.4", + "@img/sharp-libvips-linux-riscv64": "1.3.4", + "@img/sharp-libvips-linux-s390x": "1.3.4", + "@img/sharp-libvips-linux-x64": "1.3.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4", + "@img/sharp-libvips-linuxmusl-x64": "1.3.4", + "@img/sharp-linux-arm": "0.35.5", + "@img/sharp-linux-arm64": "0.35.5", + "@img/sharp-linux-ppc64": "0.35.5", + "@img/sharp-linux-riscv64": "0.35.5", + "@img/sharp-linux-s390x": "0.35.5", + "@img/sharp-linux-x64": "0.35.5", + "@img/sharp-linuxmusl-arm64": "0.35.5", + "@img/sharp-linuxmusl-x64": "0.35.5", + "@img/sharp-webcontainers-wasm32": "0.35.5", + "@img/sharp-win32-arm64": "0.35.5", + "@img/sharp-win32-ia32": "0.35.5", + "@img/sharp-win32-x64": "0.35.5" }, "peerDependenciesMeta": { "@types/node": { @@ -8220,9 +8220,10 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } diff --git a/public/freezmo-app.webp b/public/freezmo-app.webp new file mode 100644 index 0000000..6d62067 Binary files /dev/null and b/public/freezmo-app.webp differ diff --git a/src/app/components/ProjectIndex.tsx b/src/app/components/ProjectIndex.tsx new file mode 100644 index 0000000..2b78bad --- /dev/null +++ b/src/app/components/ProjectIndex.tsx @@ -0,0 +1,140 @@ +import type { CSSProperties, ReactNode } from "react"; +import { + codingProjects, + techProjects, + type CodingProject, + type CodingProjectGroup, + type ProjectStatus, + type TechProject, + type TechProjectGroup, +} from "../data"; + +const STATUS_LABEL: Record = { + finished: "Finished", + live: "Live", + wip: "WIP", + unfinished: "Unfinished", + discontinued: "Discontinued", + forgotten: "Forgotten", +}; + +const PROJECT_GROUPS: { id: CodingProjectGroup; title: string }[] = [ + { id: "games", title: "Games & game jams" }, + { id: "linux", title: "Linux & desktop" }, + { id: "bots", title: "Bots, servers & plugins" }, + { id: "apps", title: "Apps & experiments" }, +]; + +const HARDWARE_GROUPS: { id: TechProjectGroup; title: string }[] = [ + { id: "desktops", title: "Desktops & servers" }, + { id: "laptops", title: "Laptops" }, + { id: "phones", title: "Phones" }, + { id: "consoles", title: "Consoles & handhelds" }, +]; + +/** + * Grouped, repo-listing-style index that replaced the old card gallery. + * Coding rows: language-coloured dot — title (+ status pill) over the + * description — host/language tag. Hardware rows: plain rows with the year + * on the right. Coding rows are links; hardware rows are static. + */ +function Group({ + title, + count, + children, +}: { + title: string; + count: number; + children: ReactNode; +}) { + return ( +
+

+ {title} + {count} +

+
{children}
+
+ ); +} + +function CodingRow({ project }: { project: CodingProject }) { + return ( + + + ); +} + +function HardwareRow({ project }: { project: TechProject }) { + return ( +
+ + + {project.title} + + {project.desc} + + {project.year ?? ""} +
+ ); +} + +export function CodingProjectIndex() { + return ( +
+ {PROJECT_GROUPS.map((group) => { + const items = codingProjects.filter((p) => p.group === group.id); + if (!items.length) return null; + return ( + + {items.map((project) => ( + + ))} + + ); + })} +
+ ); +} + +export function HardwareProjectIndex() { + return ( +
+ {HARDWARE_GROUPS.map((group) => { + const items = techProjects.filter((p) => p.group === group.id); + if (!items.length) return null; + return ( + + {items.map((project) => ( + + ))} + + ); + })} +
+ ); +} diff --git a/src/app/components/WebLayout.tsx b/src/app/components/WebLayout.tsx index 7fc9e4c..b2ab559 100644 --- a/src/app/components/WebLayout.tsx +++ b/src/app/components/WebLayout.tsx @@ -6,10 +6,11 @@ import JokerLogo from "./JokerLogo"; import ServiceButton from "./ServiceButton"; import ContributionHeatmap from "./ContributionHeatmap"; import FeatureWindow from "./FeatureWindow"; +import { CodingProjectIndex, HardwareProjectIndex } from "./ProjectIndex"; import Clock from "./Clock"; import { useTheme } from "./useTheme"; import { useColorScheme } from "./useColorScheme"; -import { socials, codingProjects, techProjects, friends } from "../data"; +import { socials, friends } from "../data"; const NAV = [ { id: "overview", label: "Overview" }, @@ -234,6 +235,23 @@ export default function WebLayout() { +
+ Freezmo quiz screen — a history question about the Schuman plan with AI grading feedback +

+ Started working on a new project Freezmo — basically a free version of the + famous Gizmo app, but instead of paying for AI you use your ollama free cloud + API key. Notes in, flashcards and quizzes out. Try it at{" "} + freezmo.dvorakmortonxd.dev. +

+
+
@@ -246,7 +264,7 @@ export default function WebLayout() {

-
+

A lightweight browser made in Rust with WebKitGTK. It's the successor to my @@ -267,37 +285,11 @@ export default function WebLayout() {

-
- {codingProjects.map((project, idx) => ( - - -

{project.title}

-

{project.desc}

-
- ))} -
+
-
- {techProjects.map((project, idx) => ( -
- -

{project.title}

-

{project.desc}

-
- ))} -
+
diff --git a/src/app/components/apps.tsx b/src/app/components/apps.tsx index 7df7a3a..0643cb0 100644 --- a/src/app/components/apps.tsx +++ b/src/app/components/apps.tsx @@ -2,15 +2,11 @@ import Image from "next/image"; import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, type ReactNode } from "react"; -import { - socials, - codingProjects, - techProjects, - friends, -} from "../data"; +import { socials, friends } from "../data"; import ServiceButton from "./ServiceButton"; import ContributionHeatmap from "./ContributionHeatmap"; import FeatureWindow from "./FeatureWindow"; +import { CodingProjectIndex, HardwareProjectIndex } from "./ProjectIndex"; import JokerLogo from "./JokerLogo"; import { setTheme } from "./useTheme"; @@ -107,10 +103,14 @@ function NowApp() {

I'm currently hosting an SMP (dm me on discord). Also I'm pretty much - cooking daily, because im bulking through out the non-summer seasons. And me and - my pal Pepa are working on an education app so we - can study more efficiently, It's called{" "} - maturita.c! + cooking daily, because im bulking through out the non-summer seasons. I started + working on a new project{" "} + Freezmo, basically a free + version of the famous Gizmo app but instead of paying for AI you use your ollama + free cloud api key. The education app I started with my pal{" "} + Pepa, maturita.c, now lives on as{" "} + Graduately under his + wing.

@@ -204,23 +204,7 @@ function ServicesApp() { function ProjectsApp() { return (
-
- {codingProjects.map((project, idx) => ( - - -

{project.title}

-

{project.desc}

-
- ))} -
+
); } @@ -228,17 +212,7 @@ function ProjectsApp() { function HardwareApp() { return (
-
- {techProjects.map((project, idx) => ( -
- -

{project.title}

-

{project.desc}

-
- ))} -
+
); } @@ -480,7 +454,7 @@ function RevivalApp() { function RustyWolfApp() { return (
-

Introducing RustyWolf

+

RustyWolf

What makes it so cool???

@@ -513,7 +487,7 @@ const TERMINAL_FILES: Record = { "about_me.md": "Hey, I'm Martin Dvorak, a 17 year old IT student from the Czech Republic.\nI self-host way too many things and tinker with GNU/Linux.", "now.txt": - "Currently hosting an SMP and building an education app with Pepa.", + "Currently hosting an SMP. Started working on a new project Freezmo, basically a free version of the famous Gizmo app but instead of paying for AI you use your ollama free cloud api key.", "resume.txt": "sssvt.cz - network management & administration (2025-)\nGentoo, SwayFX, RustyWolf, dxdwm, Revival Inc.", }; diff --git a/src/app/data.ts b/src/app/data.ts index 804d6b3..47b2032 100644 --- a/src/app/data.ts +++ b/src/app/data.ts @@ -4,19 +4,46 @@ export interface Social { url: string; } +/** Lifecycle state of a coding project, shown as a chip on its index row. */ +export type ProjectStatus = + | "finished" + | "live" + | "wip" + | "unfinished" + | "discontinued" + | "forgotten"; + +/** Section a coding project is filed under in the Projects index. */ +export type CodingProjectGroup = "games" | "linux" | "bots" | "apps"; + export interface CodingProject { title: string; desc: string; - /** Emoji glyph shown on the card's CSS gradient tile (no image assets). */ - emoji: string; + /** Stable key for the index row (also the React key), e.g. `rustywolf`. */ + slug: string; + /** Index group the project is listed under. */ + group: CodingProjectGroup; + /** Status chip on the row; omitted for grab-bag entries. */ + status?: ProjectStatus; + /** Language or host badge on the row. */ + tag: string; + /** Hex accent for the row dot + hover tint. */ + accent: string; url: string; } +/** Section a device is filed under in the Hardware index. */ +export type TechProjectGroup = "desktops" | "laptops" | "phones" | "consoles"; + export interface TechProject { title: string; desc: string; - /** Emoji glyph shown on the card's CSS gradient tile (no image assets). */ - emoji: string; + /** Stable key for the index row (also the React key), e.g. `macbook-air-m4`. */ + slug: string; + /** Index group the device is listed under. */ + group: TechProjectGroup; + /** Model / build year, shown on the right when known. */ + year?: string; } export interface Friend { @@ -54,190 +81,317 @@ export const socials: Social[] = [ export const codingProjects: CodingProject[] = [ { - title: "Hospital Execution (Unfinished)", + title: "Hospital Execution", desc: "the first ever real game I made, in pygame. I've abandoned it.", - emoji: "🏥", + slug: "hospital-execution", + group: "games", + status: "unfinished", + tag: "itch.io", + accent: "#fa5c5c", url: "https://martin-dv.itch.io/hospital-execution-demo", }, { - title: "Underbaranoia (Finished)", + title: "Underbaranoia", desc: "basically a undertale like infinite fight simulator that gets progressively harder, made in pygame.", - emoji: "⚔️", + slug: "underbaranoia", + group: "games", + status: "finished", + tag: "itch.io", + accent: "#fa5c5c", url: "https://martin-dv.itch.io/underbaranoia", }, { - title: "Offline memer (Finished)", + title: "Offline memer", desc: "parody of the discord bot \"Dank Memer\" made in batch. (this was technically my first ever game I published).", - emoji: "🤖", + slug: "offline-memer", + group: "games", + status: "finished", + tag: "itch.io", + accent: "#fa5c5c", url: "https://martin-dv.itch.io/offline-memer", }, { - title: "4y (Forgotten)", + title: "The Larvae", + desc: "my entry for Mini Jam 212 (theme: Control), made in pygame. you spawn in a well developed city and parasite on people with your manipulative powers until you get so rich you destroy it.", + slug: "the-larvae", + group: "games", + status: "unfinished", + tag: "Python", + accent: "#cf6bd6", + url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/the-larvae", + }, + { + title: "4y", desc: "just a renamed fork of the ly login manager (based login manager btw I love it), no extra features, just a rename, its actually outdated so dont use it.", - emoji: "🔐", + slug: "4y", + group: "linux", + status: "forgotten", + tag: "C", + accent: "#7d8590", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/4y", }, { - title: "4rch linux (Forgotten)", + title: "4rch linux", desc: "same as above, basically just a renamed fork of arch linux with calamares installer, also outdated and not maintained at all so no use please.", - emoji: "🐧", + slug: "4rch-linux", + group: "linux", + status: "forgotten", + tag: "Shell", + accent: "#89e051", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/4rch-linux", }, { - title: "You_Are_An_Idiot_Virus.py (Finished)", + title: "You_Are_An_Idiot_Virus.py", desc: "this is just a python script that just spams blinking \"you are an idiot\" windows, made it as a prank I think, not really sure rn.", - emoji: "🪟", + slug: "uranidiot", + group: "apps", + status: "finished", + tag: "Python", + accent: "#3572A5", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/uranidiot", }, { - title: "Venturesome (Discontinued)", + title: "Venturesome", desc: "a browser I wrote in python using PyQtWebEngine with PyQt5, actually pretty cool and modular but I couldnt get past the stage of adding a tab system, basically surpassed by my other project: RustyWolf.", - emoji: "🌐", + slug: "venturesome", + group: "linux", + status: "discontinued", + tag: "Python", + accent: "#3572A5", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/Venturesome", }, { - title: "Mandelbrot set in Pygame (Finished)", + title: "Mandelbrot set in Pygame", desc: "a python pygame script that renders the mandelbrot set, made it when I was fascinated by how it looks and ngl it still looks cool af.", - emoji: "🌀", + slug: "mandelbrot", + group: "apps", + status: "finished", + tag: "Python", + accent: "#8b5cf6", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/mandelbrot", }, { - title: "Underpygametale (Unfinished)", + title: "Underpygametale", desc: "a remake of undertale written in pygame, got it to about the flowey part (at the beginning) and didnt touch it in a long time.", - emoji: "💀", + slug: "underpygametale", + group: "games", + status: "unfinished", + tag: "Python", + accent: "#ef476f", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/underpygametale", }, { title: "Many discord bots...", - desc: "so many of them, once I (allegedly, pls discord dont ban me) even wrote a \"self-bot\" which auto-advertised a minecraft server on minecraft discord server in lfg-hosting every two hours, around 800 people joined in total.", - emoji: "💬", - url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/PYGETEX", + desc: "so many of them, once I (allegedly, pls discord dont ban me) even wrote a \"self-bot\" (lfg-bot) which auto-advertised a minecraft server on minecraft discord server in lfg-hosting every two hours, around 800 people joined in total.", + slug: "lfg-bot", + group: "bots", + tag: "Python", + accent: "#5865F2", + url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/lfg-bot", }, { - title: "MMO minecraft plugin (Unfinished)", + title: "MMO minecraft plugin", desc: "a minceraft plugin with custom bosses, items, and functions. pretty barebones and basic but I did it all manually before vibecoding was even a thing so what.", - emoji: "⛏️", + slug: "mmo-plugin", + group: "bots", + status: "unfinished", + tag: "YouTube", + accent: "#ff3d3d", url: "https://www.youtube.com/watch?v=cSAX5Ds61ac", }, { title: "Many many failed minecraft servers..", desc: "creative games, softcraft, frostville, eusmp, eurthsmp, softsmp and many other SMPs that died later on. I cant even count how many mc servers I had in total.", - emoji: "🧱", + slug: "smp-graveyard", + group: "bots", + tag: "Discord", + accent: "#62b47a", url: "https://discord.gg/KtHRm9kRmy", }, { - title: "Swords and Sandals 2 pygame remake (Unfinished)", + title: "Swords and Sandals 2 pygame remake", desc: "an unfinished remake of swords and sandals 2 in pygame, I got bored of it and never finished it but ill finish it one day for sure lol.", - emoji: "🗡️", + slug: "sas2py", + group: "games", + status: "unfinished", + tag: "Python", + accent: "#d97706", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/sas2py", }, { title: "Llama.cpp server", desc: "my llama.cpp vm running on my proxmox with a gpu passthroughed RTX 3070, dm me if u wanna test it lol.", - emoji: "🦾", + slug: "llama-cpp", + group: "bots", + status: "live", + tag: "self-hosted", + accent: "#76b900", url: "https://ai.dvorakmortonxd.dev/", }, { - title: "Batch MSDOS Simulator (Finished)", + title: "Batch MSDOS Simulator", desc: "a freshman school project on making games in batch, it was like an OS simulator with a web browser, games, photos, even a video suprise (youll have to try it to figure that one out lol).", - emoji: "💾", + slug: "dvorakmsdos", + group: "linux", + status: "finished", + tag: "Batchfile", + accent: "#b6d94c", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/DvorakMSDOS", }, { - title: "RustyWolf (WIP, Available now!)", - desc: "a browser I made in rust with webkitgtk, I made it to be lightweight and to be able to be ran on macbook unibody 2010 before I realised I got scammed.. It's the successor to my previous project Venturesome :)", - emoji: "🐺", + title: "RustyWolf", + desc: "my privacy focused browser made in rust with webkitgtk, made lightweight so it can run on a macbook unibody 2010 before I realised I got scammed.. It's the successor to my previous project Venturesome :)", + slug: "rustywolf", + group: "linux", + status: "wip", + tag: "Rust", + accent: "#dea584", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/RustyWolf", }, { - title: "dxdwm (Discontinued)", - desc: "a small x11 window manager written in rust.", - emoji: "🪟", + title: "dxdwm", + desc: "a small x11 window manager. originally written in rust (dxdwm-rs), now continued in C.", + slug: "dxdwm", + group: "linux", + status: "discontinued", + tag: "C", + accent: "#94a3b8", url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/dxdwm", }, { - title: "Revival Inc. (Finished)", + title: "Revival Inc.", desc: "My game written in pygame and packaged with pygbag made for the Mini Jame Gam #55! tho I only made it in 6 hours lmao", - emoji: "🧟", + slug: "revival-inc", + group: "games", + status: "finished", + tag: "Python", + accent: "#10b981", url: "https://dvorakmortonxd.dev/revival-inc", }, + { + title: "freezmo", + desc: "a free version of the famous Gizmo app: notes in, flashcards and quizzes out — instead of paying for AI you use your own ollama free cloud api key.", + slug: "freezmo", + group: "apps", + status: "wip", + tag: "TypeScript", + accent: "#3178c6", + url: "https://freezmo.dvorakmortonxd.dev", + }, + { + title: "qol-tweaks", + desc: "my quality of life plugin for the dvorakmortonxd SMP.", + slug: "qol-tweaks", + group: "bots", + status: "live", + tag: "Java", + accent: "#b07219", + url: "https://git.dvorakmortonxd.dev/dvorakmortonxd/qol-tweaks", + }, ]; export const techProjects: TechProject[] = [ { title: "Gentoo Setup", desc: "my main computer with gentoo and SwayFX. specs: Ryzen 5 3600 (6c/12t), RX 580 8GB ASUS ROG, 16gb of ram and a 240gb sata ssd.", - emoji: "🐧", + slug: "gentoo-swayfx", + group: "desktops", }, { title: "Proxmox Server", desc: "my personal proxmox server (dm me on ig if u need a VPS/hosting), specs: Xeon E5 2680 v4 (14c/28t), RTX 3070 (llama.cpp), 68gb ddr4 rdimm ram (2*16gb, 1*32gb, 1*4gb), 256gb of sata m2 space + 1tb hdd + 750gb hdd.", - emoji: "🖥️", + slug: "proxmox-server", + group: "desktops", }, { title: "Xbox 360 S (badupdate)", desc: "xbox 360 slim (trinity) with badupdate exploit, allowing to boot custom software. (not my photo), the specs are XCGPU (3c/6t), 0.5GB of gddr3 ram and a 500gb hdd.", - emoji: "🎮", + slug: "xbox-360-s", + group: "consoles", + year: "2010", }, { title: "Lenovo Legion Go S", desc: "my gaming handheld which I sometimes use as a computer, it has 32gb of unified lpddr5x memory and 1tb of nvme storage, I dualboot artix linux (openrc) with SwayFX and stock SteamOS on it.", - emoji: "🕹️", + slug: "legion-go-s", + group: "consoles", + year: "2025", }, { title: "Macbook Air M4 13\"", desc: "my main device for basically everything on the go except gaming. specs are Apple M4 (cpu:10c,gpu:8c), 16gb of unified ram (lpddr5x), 256gb Storage.", - emoji: "💻", + slug: "macbook-air-m4", + group: "laptops", + year: "2025", }, { title: "Macbook Air 2013 11\"", desc: "bought this for tinkering lol, specs are intel core i5 (2c/4t), 8gb of ddr3 ram and 250gb ssd, installed arch linux on it with i3wm.", - emoji: "💻", + slug: "macbook-air-2013", + group: "laptops", + year: "2013", }, { title: "iPhone 7 128gb", desc: "somehow found a listing for 4 bucks (refurbed.cz) for it so I got it lol, it has a little dent I marked it on the photo (which isnt mine btw), except cosmetic damage its pretty much fully functional, specs are Apple A10 (4c/4t), 2gb of ram and 128gb of storage", - emoji: "📱", + slug: "iphone-7", + group: "phones", + year: "2016", }, { title: "Macbook Unibody 2010", desc: "found random listing on bazos for 15 bucks but after I bought a power adapter it turned out to be non functioning so I got scammed :(", - emoji: "💻", + slug: "macbook-unibody-2010", + group: "laptops", + year: "2010", }, { title: "ThinkPad T400s 14\"", desc: "got it from a random guy for 20 bucks, its an old laptop from 2009. I put void linux on it and i3wm on it, specs are intel core 2 duo (2c/2t), 8gb ddr3 ram and 800gb hdd.", - emoji: "💻", + slug: "thinkpad-t400s", + group: "laptops", + year: "2009", }, { title: "Asus N56JR 15.6\"", desc: "one of my first laptops my dad got for me when I was like 12, still works but the battery is KO, specs are intel core i7 4700HQ (4c/8t), 8gb ddr3 ram and 240gb ssd, it currently runs ubuntu linux 24.04LTS and my mom uses it for movies and shows.", - emoji: "💻", + slug: "asus-n56jr", + group: "laptops", + year: "2013", }, { title: "Small Unknown XP Acer Laptop", desc: "found that one in ewaste, I think it has like 2gb of ram and an intel atom, not sure what to do with it yet", - emoji: "📟", + slug: "unknown-acer-xp", + group: "laptops", }, { title: "Dell Latitude E6320", desc: "also from ewaste, put mint on it but didnt do anything yet, lowk kinda capable for its time in 2011 so I might put it to use later but the battery is KO.", - emoji: "💻", + slug: "latitude-e6320", + group: "laptops", + year: "2011", }, { title: "iPhone 11 128gb", desc: "my first iphone I got from my parents at 13, rn my dad has it because I switched over to the iphone 16 pro in 2025, specs are Apple A13 (6c/6t), 4gb of ram and 128gb of storage. (NOT MY IMAGE)", - emoji: "📱", + slug: "iphone-11", + group: "phones", + year: "2019", }, { title: "iPhone 16 Pro 128gb", desc: "originally wanted iphone 13 mini (because of the size) but I somehow decided to get 16 pro, which is a bit smaller than my older iphone 11, specs are Apple A18 pro (6c/6t), (btw this chip is the same chip used in the macbook neo so thats cool) and 8gb of ram and 128gb of storage, my main phone.", - emoji: "📱", + slug: "iphone-16-pro", + group: "phones", + year: "2025", }, { title: "Xbox one S 2TB", desc: "my dad bought it for me also in like 2018 or 2019 and I sometimes play the console edition of minecraft because I like to play the gliding minigame on it when someone comes over.", - emoji: "🎮", + slug: "xbox-one-s", + group: "consoles", + year: "2016", }, ]; diff --git a/src/app/skeuo.css b/src/app/skeuo.css index 7f1db1e..74e7b56 100644 --- a/src/app/skeuo.css +++ b/src/app/skeuo.css @@ -852,41 +852,6 @@ a.win-icon { color: #9a9a9a; } -.app-surface .project-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); - gap: 12px; -} -.app-surface .project-card { - padding: 10px; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 6px; - background: linear-gradient(to bottom, #ffffff, #f0f4fa); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14); -} -.app-surface .project-card:hover { - border-color: #7db9e8; - background: #ffffff; - box-shadow: 0 0 0 1px #7db9e8, 0 0 14px rgba(110, 185, 255, 0.5), - 0 8px 18px rgba(0, 25, 55, 0.2); -} -.app-surface .project-thumb { - height: 150px; - border-radius: 4px; - border: 1px solid rgba(0, 0, 0, 0.12); -} -.app-surface .project-title { - color: #0e3355; -} -.app-surface .project-card:hover .project-title { - color: #0d5aa7; -} -.app-surface .project-desc { - color: #43607c; -} -.app-surface .project-card:hover .project-desc { - color: #1d3e5c; -} .app-surface .gym-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); @@ -1151,29 +1116,29 @@ a.win-icon { .win-body .service-button:hover .service-desc { color: #d3dae3; } -.win-body .project-card { - border-color: #1b1e20; - background: linear-gradient(to bottom, #31363b, #2a2e32); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); +/* Project/Hardware index inside the dark KDE windows. */ +.win-body { + --index-line: rgba(255, 255, 255, 0.07); + --status-finished: #4ade80; + --status-live: #60a5fa; + --status-wip: #fbbf24; + --status-unfinished: #fb923c; + --status-discontinued: #f87171; + --status-forgotten: #94a3b8; } -.win-body .project-card:hover { - border-color: #3daee9; - background: #353b40; - box-shadow: 0 0 0 1px #3daee9, 0 0 14px rgba(61, 174, 233, 0.45); +.win-body .index-list { + background: rgba(255, 255, 255, 0.03); } -.win-body .project-thumb { - border-color: #1b1e20; -} -.win-body .project-title { +.win-body .index-title { color: #eff0f1; } -.win-body .project-card:hover .project-title { - color: #3daee9; -} -.win-body .project-desc { +.win-body .index-desc { color: #b0b6bc; } -.win-body .project-card:hover .project-desc { +.win-body a.index-row:hover { + background: rgba(255, 255, 255, 0.06); +} +.win-body a.index-row:hover .index-desc { color: #d3dae3; } @@ -1600,9 +1565,6 @@ html[data-theme="skeuo"] .fw { .app-pad { padding: 14px; } - .app-surface .project-grid { - grid-template-columns: 1fr; - } .app-surface .social-buttons { grid-template-columns: 1fr 1fr; } @@ -1613,8 +1575,14 @@ html[data-theme="skeuo"] .fw { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; } - .app-surface .project-thumb { - height: 140px; + .app-surface .index-group-head { + font-size: 0.6rem; + } + .app-surface .index-row { + padding: 10px 11px; + } + .app-surface .index-desc { + font-size: 0.75rem; } } diff --git a/src/app/web.css b/src/app/web.css index 45338cd..6c18d28 100644 --- a/src/app/web.css +++ b/src/app/web.css @@ -44,6 +44,15 @@ --red: #e11d48; --darkpink: #db2777; + /* Project/Hardware index tokens */ + --index-line: rgba(16, 24, 43, 0.1); + --status-finished: #15803d; + --status-live: #1d4ed8; + --status-wip: #b45309; + --status-unfinished: #c2410c; + --status-discontinued: #b91c1c; + --status-forgotten: #64748b; + --web-font: "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-custom-mono: ui-monospace, "JetBrains Mono", "SFMono-Regular", Menlo, Consolas, @@ -84,6 +93,15 @@ html[data-theme="web"][data-scheme="dark"] { --purple: #c084fc; --red: #fb7185; --darkpink: #f472b6; + + /* Project/Hardware index tokens */ + --index-line: rgba(255, 255, 255, 0.09); + --status-finished: #4ade80; + --status-live: #60a5fa; + --status-wip: #fbbf24; + --status-unfinished: #fb923c; + --status-discontinued: #f87171; + --status-forgotten: #94a3b8; } html[data-theme="web"] { @@ -430,6 +448,17 @@ html[data-theme="web"] body { display: flex; flex-direction: column; } +/* Real app screenshot inside a feature panel (Freezmo) — framed like the CSS + mock windows so it sits in the same visual language. */ +.web-feature-shot { + display: block; + width: 100%; + height: auto; + margin-bottom: 14px; + border-radius: 16px; + border: 1px solid var(--glass-border); + box-shadow: 0 18px 36px -22px rgba(23, 32, 60, 0.5); +} /* ============================================================ FEATURE WINDOWS Asset-free decorative mock windows that replace the old @@ -1161,78 +1190,145 @@ html[data-theme="web"] body { } /* ============================================================ - PROJECTS / HARDWARE - ============================================================ */ -.project-grid { - /* Masonry-ish gallery: multi-column packs the cards tightly, so a short card - never leaves a half-empty slot under a tall neighbour. */ - columns: 3 250px; - column-gap: 14px; + PROJECTS / HARDWARE INDEX + ------------------------------------------------------------ + Grouped repo-listing layout: per-section group headers, then + rows of accent dot – title (+ status) over description – tag / + year. Replaced the old card gallery. */ +.index-groups { + display: flex; + flex-direction: column; + gap: 22px; } -.project-card { - display: block; - break-inside: avoid; - -webkit-column-break-inside: avoid; - margin-bottom: 14px; - padding: 12px; - border-radius: 16px; - border: 1px solid var(--btn-border, var(--glass-border)); +.index-group-head { + display: flex; + align-items: center; + gap: 10px; + margin: 0 0 8px; + font-family: var(--font-custom-mono); + font-size: 0.66rem; + font-weight: 700; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--gray); +} +.index-group-count { + font-weight: 600; + color: color-mix(in srgb, var(--gray) 55%, transparent); +} +.index-group-head::after { + content: ""; + flex: 1; + height: 1px; + background: var(--index-line); +} +.index-list { + border: 1px solid var(--index-line); + border-radius: 12px; + overflow: hidden; background: var(--btn-bg, var(--glass-lo)); - box-shadow: var(--btn-shadow, none); +} +.index-list > * + * { + border-top: 1px solid var(--index-line); +} +.index-row { + display: grid; + grid-template-columns: 10px minmax(0, 1fr) auto; + gap: 14px; + align-items: start; + padding: 11px 14px; color: inherit; text-decoration: none; - transition: transform 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease, - background-color 0.22s ease; } -.project-card:hover { - transform: translateY(-4px); - border-color: var(--accent-line); +/* Hardware rows: no accent dot (it carried no meaning there), so the body + takes the full first track. */ +.index-row-plain { + grid-template-columns: minmax(0, 1fr) auto; +} +a.index-row { + transition: background-color 0.16s ease; +} +a.index-row:hover { background: var(--btn-bg-hi, var(--glass-hi)); - box-shadow: 0 20px 38px -20px rgba(23, 32, 60, 0.55); } -.project-thumb { - display: grid; - place-items: center; - height: 150px; - width: 100%; - margin-bottom: 12px; - border-radius: 12px; - border: 1px solid var(--glass-border); - font-size: 2.6rem; - line-height: 1; - user-select: none; - text-shadow: 0 3px 10px rgba(0, 0, 0, 0.35); +.index-dot { + width: 9px; + height: 9px; + margin-top: 6px; + border-radius: 50%; + background: var(--index-accent, var(--accent)); + box-shadow: 0 0 9px color-mix(in srgb, var(--index-accent, var(--accent)) 55%, transparent); } -/* Shared gradient palette for the card tiles (no image assets). */ -.thumb-0 { - background: linear-gradient(150deg, #6d5efc, #2f8bff); +.index-line1 { + display: flex; + align-items: baseline; + flex-wrap: wrap; + gap: 8px; } -.thumb-1 { - background: linear-gradient(150deg, #ec4899, #db2777); -} -.thumb-2 { - background: linear-gradient(150deg, #f59e0b, #d97757); -} -.thumb-3 { - background: linear-gradient(150deg, #10b981, #0d9488); -} -.thumb-4 { - background: linear-gradient(150deg, #8b5cf6, #6366f1); -} -.thumb-5 { - background: linear-gradient(150deg, #06b6d4, #3b82f6); -} -.project-title { - font-size: 0.95rem; +.index-title { + font-size: 0.92rem; font-weight: 700; + color: var(--fg); } -.project-card:hover .project-title { - color: var(--accent); +a.index-row:hover .index-title { + color: color-mix(in srgb, var(--index-accent, var(--accent)) 72%, var(--fg)); } -.project-desc { - margin-top: 4px; - font-size: 0.8rem; - color: var(--web-muted); +.index-status { + padding: 1px 7px 2px; + border-radius: 999px; + border: 1px solid color-mix(in srgb, currentColor 32%, transparent); + background: color-mix(in srgb, currentColor 10%, transparent); + font-family: var(--font-custom-mono); + font-size: 0.56rem; + font-weight: 700; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--status-forgotten); +} +.index-status-finished { + color: var(--status-finished); +} +.index-status-live { + color: var(--status-live); +} +.index-status-wip { + color: var(--status-wip); +} +.index-status-unfinished { + color: var(--status-unfinished); +} +.index-status-discontinued { + color: var(--status-discontinued); +} +.index-status-forgotten { + color: var(--status-forgotten); +} +.index-desc { + display: block; + margin-top: 3px; + font-size: 0.78rem; + line-height: 1.5; + color: var(--gray); +} +.index-meta { + display: inline-flex; + align-items: center; + gap: 10px; + padding-top: 3px; + font-family: var(--font-custom-mono); + font-size: 0.62rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--gray); + white-space: nowrap; +} +.index-arrow { + transition: transform 0.16s ease, color 0.16s ease; +} +a.index-row:hover .index-arrow { + transform: translate(2px, -2px); + color: color-mix(in srgb, var(--index-accent, var(--accent)) 72%, var(--fg)); } /* ============================================================ @@ -1750,27 +1846,20 @@ html[data-theme="web"][data-scheme="dark"] .heatmap-legend-cell[data-level="4"] font-size: 0.82rem; font-weight: 600; } - /* Projects/hardware gallery: 2-up on phones instead of one full-width card - per row, with a shorter image + tighter card so a row is compact. */ - .project-grid { - columns: 2; - column-gap: 10px; + /* Projects/hardware index: tighter rows on phones. */ + .index-groups { + gap: 18px; } - .project-card { - margin-bottom: 10px; - padding: 10px; + .index-row { + gap: 10px; + padding: 10px 11px; } - .project-thumb { - height: 90px; - margin-bottom: 8px; - font-size: 1.8rem; - } - .project-title { - font-size: 0.88rem; - } - .project-desc { + .index-desc { font-size: 0.75rem; } + .index-meta { + font-size: 0.58rem; + } .services-buttons, .services-buttons.services-main { grid-template-columns: 1fr;