workstations and light theme
@@ -2,6 +2,10 @@
|
|||||||
{
|
{
|
||||||
"description": "A personal page for projects, stack notes, and developer work.",
|
"description": "A personal page for projects, stack notes, and developer work.",
|
||||||
"key": "web",
|
"key": "web",
|
||||||
|
"links": {
|
||||||
|
"homepage": "https://scuroneko.dev",
|
||||||
|
"sources": "https://git.scuroneko.dev/ScuroNeko/scuroneko.dev"
|
||||||
|
},
|
||||||
"name": "ScuroNeko.dev",
|
"name": "ScuroNeko.dev",
|
||||||
"stack": ["html", "css", "js"],
|
"stack": ["html", "css", "js"],
|
||||||
"status": "active",
|
"status": "active",
|
||||||
@@ -16,6 +20,6 @@
|
|||||||
"name": "Laniakea",
|
"name": "Laniakea",
|
||||||
"stack": ["go", "tg"],
|
"stack": ["go", "tg"],
|
||||||
"status": "active",
|
"status": "active",
|
||||||
"tone": "purple"
|
"tone": "rose"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"$id": "https://scuroneko.dev/schemas/links.schema.json",
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tone": {
|
||||||
|
"$ref": "./shared.schema.json#/$defs/tone"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"format": "uri",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["key", "name", "label", "url", "tone"],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"title": "Links",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"$id": "https://scuroneko.dev/schemas/projects.schema.json",
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "uri",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"stack": {
|
||||||
|
"items": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": ["active", "archive", "wip", "paused"],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tone": {
|
||||||
|
"$ref": "./shared.schema.json#/$defs/tone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["key", "name", "description", "stack", "status", "tone"],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"title": "Projects",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$defs": {
|
||||||
|
"tone": {
|
||||||
|
"enum": [
|
||||||
|
"blue",
|
||||||
|
"gold",
|
||||||
|
"mint",
|
||||||
|
"purple",
|
||||||
|
"red",
|
||||||
|
"cyan",
|
||||||
|
"green",
|
||||||
|
"pink",
|
||||||
|
"teal",
|
||||||
|
"lime",
|
||||||
|
"rose"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$id": "https://scuroneko.dev/schemas/shared.schema.json",
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "Shared schema definitions"
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"$id": "https://scuroneko.dev/schemas/stack.schema.json",
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"hide": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"items": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true
|
||||||
|
},
|
||||||
|
"tone": {
|
||||||
|
"$ref": "./shared.schema.json#/$defs/tone"
|
||||||
|
},
|
||||||
|
"years": {
|
||||||
|
"minimum": 0,
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["key", "name", "tone", "years"],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"title": "Stack",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"$id": "https://scuroneko.dev/schemas/workstations.schema.json",
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"actual": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["key", "name"],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"specs": {
|
||||||
|
"properties": {
|
||||||
|
"cpu": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"gpu": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"os": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ram": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"capacity": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"minLength": 1,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name", "capacity"],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"tone": {
|
||||||
|
"$ref": "./shared.schema.json#/$defs/tone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["key", "name", "tone"],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"title": "Workstations",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
@@ -45,6 +45,20 @@
|
|||||||
"tone": "blue",
|
"tone": "blue",
|
||||||
"years": 2
|
"years": 2
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "jetbrains",
|
||||||
|
"name": "JetBrains IDE",
|
||||||
|
"tags": ["tools"],
|
||||||
|
"tone": "purple",
|
||||||
|
"years": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "vscode",
|
||||||
|
"name": "Visual Studio Code",
|
||||||
|
"tags": ["tools"],
|
||||||
|
"tone": "purple",
|
||||||
|
"years": 7
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"hide": true,
|
"hide": true,
|
||||||
"key": "html",
|
"key": "html",
|
||||||
@@ -65,5 +79,12 @@
|
|||||||
"name": "JavaScript",
|
"name": "JavaScript",
|
||||||
"tone": "gold",
|
"tone": "gold",
|
||||||
"years": 7
|
"years": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hide": true,
|
||||||
|
"key": "sass",
|
||||||
|
"name": "Sass",
|
||||||
|
"tone": "rose",
|
||||||
|
"years": 5
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actual": true,
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"key": "monitor1",
|
||||||
|
"name": "AOC 24G2SPU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "monitor2",
|
||||||
|
"name": "AOC 24E1Q"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "keyboard",
|
||||||
|
"name": "Ardor Wakizashi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mouse",
|
||||||
|
"name": "Ardor Immortaliry PRO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "microphone",
|
||||||
|
"name": "Fifine AM8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"key": "pc",
|
||||||
|
"name": "PC",
|
||||||
|
"specs": {
|
||||||
|
"cpu": "AMD Ryzen 7 7700",
|
||||||
|
"gpu": "NVIDIA GeForce RTX 5070",
|
||||||
|
"os": "Windows 11 Pro",
|
||||||
|
"ram": "32GB DDR5",
|
||||||
|
"storage": [
|
||||||
|
{
|
||||||
|
"capacity": "1TB",
|
||||||
|
"name": "Adata XPG GAMMIX S11 Pro",
|
||||||
|
"type": "M2 PCI-E 3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"capacity": "1TB",
|
||||||
|
"name": "WD Blue",
|
||||||
|
"type": "SATA HDD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tone": "rose"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actual": true,
|
||||||
|
"key": "notebook",
|
||||||
|
"name": "Notebook",
|
||||||
|
"specs": {
|
||||||
|
"cpu": "Intel Core i3-8470U",
|
||||||
|
"gpu": "Intel UHD Graphics 620",
|
||||||
|
"os": "Windows 10 LTSC 2021",
|
||||||
|
"ram": "16GB DDR4",
|
||||||
|
"storage": [
|
||||||
|
{
|
||||||
|
"capacity": "256GB",
|
||||||
|
"name": "WD Blue SN550",
|
||||||
|
"type": "M2 PCI-E 3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"capacity": "256GB",
|
||||||
|
"name": "Neo Forza NFS12",
|
||||||
|
"type": "SATA SSD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tone": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actual": true,
|
||||||
|
"key": "vps",
|
||||||
|
"name": "VPS",
|
||||||
|
"specs": {
|
||||||
|
"cpu": "2 vCore (AMD EPYC 7763)",
|
||||||
|
"gpu": "N/A",
|
||||||
|
"os": "Arch Linux",
|
||||||
|
"ram": "4GB",
|
||||||
|
"storage": [
|
||||||
|
{
|
||||||
|
"capacity": "60GB",
|
||||||
|
"name": "NVMe SSD",
|
||||||
|
"type": "NVMe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tone": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actual": false,
|
||||||
|
"key": "pc",
|
||||||
|
"name": "PC",
|
||||||
|
"specs": {
|
||||||
|
"cpu": "Intel Core i7-6700",
|
||||||
|
"gpu": "AMD Radeon RX580",
|
||||||
|
"os": "Windows 11 Pro",
|
||||||
|
"ram": "16GB DDR4",
|
||||||
|
"storage": [
|
||||||
|
{
|
||||||
|
"capacity": "256GB",
|
||||||
|
"name": "Samsung 850 EVO",
|
||||||
|
"type": "SATA SSD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tone": "teal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 822 B After Width: | Height: | Size: 822 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 327 B After Width: | Height: | Size: 327 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>JetBrains</title><path d="M2.345 23.997A2.347 2.347 0 0 1 0 21.652V10.988C0 9.665.535 8.37 1.473 7.433l5.965-5.961A5.01 5.01 0 0 1 10.989 0h10.666A2.347 2.347 0 0 1 24 2.345v10.664a5.056 5.056 0 0 1-1.473 3.554l-5.965 5.965A5.017 5.017 0 0 1 13.007 24v-.003H2.345Zm8.969-6.854H5.486v1.371h5.828v-1.371ZM3.963 6.514h13.523v13.519l4.257-4.257a3.936 3.936 0 0 0 1.146-2.767V2.345c0-.678-.552-1.234-1.234-1.234H10.989a3.897 3.897 0 0 0-2.767 1.145L3.963 6.514Zm-.192.192L2.256 8.22a3.944 3.944 0 0 0-1.145 2.768v10.664c0 .678.552 1.234 1.234 1.234h10.666a3.9 3.9 0 0 0 2.767-1.146l1.512-1.511H3.771V6.706Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 688 B |
|
Before Width: | Height: | Size: 974 B After Width: | Height: | Size: 974 B |
|
Before Width: | Height: | Size: 527 B After Width: | Height: | Size: 527 B |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Sass</title><path d="M12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0zM9.615 15.998c.175.645.156 1.248-.024 1.792l-.065.18c-.024.061-.052.12-.078.176-.14.29-.326.56-.555.81-.698.759-1.672 1.047-2.09.805-.45-.262-.226-1.335.584-2.19.871-.918 2.12-1.509 2.12-1.509v-.003l.108-.061zm9.911-10.861c-.542-2.133-4.077-2.834-7.422-1.645-1.989.707-4.144 1.818-5.693 3.267C4.568 8.48 4.275 9.98 4.396 10.607c.427 2.211 3.457 3.657 4.703 4.73v.006c-.367.18-3.056 1.529-3.686 2.925-.675 1.47.105 2.521.615 2.655 1.575.436 3.195-.36 4.065-1.649.84-1.261.766-2.881.404-3.676.496-.135 1.08-.195 1.83-.104 2.101.24 2.521 1.56 2.43 2.1-.09.539-.523.854-.674.944-.15.091-.195.12-.181.181.015.09.091.09.21.075.165-.03 1.096-.45 1.141-1.471.045-1.29-1.186-2.729-3.375-2.7-.9.016-1.471.091-1.875.256-.03-.045-.061-.075-.105-.105-1.35-1.455-3.855-2.475-3.75-4.41.03-.705.285-2.564 4.8-4.814 3.705-1.846 6.661-1.335 7.171-.21.733 1.604-1.576 4.59-5.431 5.024-1.47.165-2.235-.404-2.431-.615-.209-.225-.239-.24-.314-.194-.12.06-.045.255 0 .375.12.3.585.825 1.396 1.095.704.225 2.43.359 4.5-.45 2.324-.899 4.139-3.405 3.614-5.505l.073.067z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 742 B After Width: | Height: | Size: 742 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg role="img" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>Visual Studio Code</title>
|
||||||
|
<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M90.767 127.126a7.968 7.968 0 0 0 6.35-.244l26.353-12.681a8 8 0 0 0 4.53-7.209V21.009a8 8 0 0 0-4.53-7.21L97.117 1.12a7.97 7.97 0 0 0-9.093 1.548l-50.45 46.026L15.6 32.013a5.328 5.328 0 0 0-6.807.302l-7.048 6.411a5.335 5.335 0 0 0-.006 7.888L20.796 64 1.74 81.387a5.336 5.336 0 0 0 .006 7.887l7.048 6.411a5.327 5.327 0 0 0 6.807.303l21.974-16.68 50.45 46.025a7.96 7.96 0 0 0 2.743 1.793Zm5.252-92.183L57.74 64l38.28 29.058V34.943Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 622 B |
@@ -3,11 +3,50 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="ScuroNeko is a Go and JavaScript developer building self-hosted tools, small web systems, and developer-focused projects."
|
||||||
|
/>
|
||||||
|
<meta name="author" content="ScuroNeko" />
|
||||||
|
<meta
|
||||||
|
name="theme-color"
|
||||||
|
content="#1f1f28"
|
||||||
|
media="(prefers-color-scheme: dark)"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="theme-color"
|
||||||
|
content="#f2ecbc"
|
||||||
|
media="(prefers-color-scheme: light)"
|
||||||
|
/>
|
||||||
|
<meta name="color-scheme" content="dark light" />
|
||||||
|
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:site_name" content="ScuroNeko" />
|
||||||
|
<meta property="og:title" content="ScuroNeko" />
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Go and JavaScript developer building self-hosted tools, small web systems, and developer-focused projects."
|
||||||
|
/>
|
||||||
|
<meta property="og:url" content="https://scuroneko.dev/" />
|
||||||
|
<meta property="og:image" content="https://scuroneko.dev/favicon.png" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary" />
|
||||||
|
<meta name="twitter:title" content="ScuroNeko" />
|
||||||
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content="Go and JavaScript developer building self-hosted tools, small web systems, and developer-focused projects."
|
||||||
|
/>
|
||||||
|
<meta name="twitter:image" content="https://scuroneko.dev/favicon.png" />
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://scuroneko.dev/" />
|
||||||
<link rel="stylesheet" href="./styles/main.css" />
|
<link rel="stylesheet" href="./styles/main.css" />
|
||||||
<link rel="stylesheet" href="./styles/hero.css" />
|
<link rel="stylesheet" href="./styles/hero.css" />
|
||||||
<link rel="stylesheet" href="./styles/stack.css" />
|
<link rel="stylesheet" href="./styles/stack.css" />
|
||||||
<link rel="stylesheet" href="./styles/projects.css" />
|
<link rel="stylesheet" href="./styles/projects.css" />
|
||||||
|
<link rel="stylesheet" href="./styles/workstations.css" />
|
||||||
<link rel="stylesheet" href="./styles/links.css" />
|
<link rel="stylesheet" href="./styles/links.css" />
|
||||||
|
<link rel="stylesheet" href="./styles/tones.css" />
|
||||||
|
<link rel="stylesheet" href="./styles/theme-light.css" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
@@ -18,11 +57,13 @@
|
|||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://storage.scuroneko.dev/fonts/FantasqueSansMono.css"
|
href="https://storage.scuroneko.dev/fonts/FantasqueSansMono.css"
|
||||||
/>
|
/>
|
||||||
<link rel="shortcut icon" href="./favicon.png" type="image/png" />
|
<link rel="shortcut icon" href="./icons/favicon-512.png" type="image/png" />
|
||||||
|
<link rel="manifest" href="./manifest.json" />
|
||||||
|
|
||||||
<script src="./js/data.js" defer></script>
|
<script src="./js/data.js" defer></script>
|
||||||
<script src="./js/stack.js" defer></script>
|
<script src="./js/stack.js" defer></script>
|
||||||
<script src="./js/projects.js" defer></script>
|
<script src="./js/projects.js" defer></script>
|
||||||
|
<script src="./js/workstations.js" defer></script>
|
||||||
<script src="./js/links.js" defer></script>
|
<script src="./js/links.js" defer></script>
|
||||||
<title>ScuroNeko</title>
|
<title>ScuroNeko</title>
|
||||||
</head>
|
</head>
|
||||||
@@ -38,6 +79,7 @@
|
|||||||
<nav class="site-nav" aria-label="Page sections">
|
<nav class="site-nav" aria-label="Page sections">
|
||||||
<a href="#stack-section">Stack</a>
|
<a href="#stack-section">Stack</a>
|
||||||
<a href="#projects-section">Projects</a>
|
<a href="#projects-section">Projects</a>
|
||||||
|
<a href="#workstations-section">Workstations</a>
|
||||||
<a href="#links-section">Links</a>
|
<a href="#links-section">Links</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,6 +93,9 @@
|
|||||||
<p class="block-subtitle">
|
<p class="block-subtitle">
|
||||||
Tools I reach for when the task needs to ship.
|
Tools I reach for when the task needs to ship.
|
||||||
</p>
|
</p>
|
||||||
|
<button class="stack-toggle" id="stack-toggle" type="button" hidden>
|
||||||
|
View all
|
||||||
|
</button>
|
||||||
<div class="stack-grid" id="stack"></div>
|
<div class="stack-grid" id="stack"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -63,9 +108,26 @@
|
|||||||
<div class="project-grid" id="projects"></div>
|
<div class="project-grid" id="projects"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block" id="links-section">
|
<section class="block" id="workstations-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<span class="section-index">03</span>
|
<span class="section-index">03</span>
|
||||||
|
<h2>Workstations</h2>
|
||||||
|
</div>
|
||||||
|
<p class="block-subtitle">Machines, peripherals, and daily drivers.</p>
|
||||||
|
<button
|
||||||
|
class="workstation-toggle"
|
||||||
|
id="workstation-toggle"
|
||||||
|
type="button"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
View all
|
||||||
|
</button>
|
||||||
|
<div class="workstation-grid" id="workstations"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="block" id="links-section">
|
||||||
|
<div class="section-heading">
|
||||||
|
<span class="section-index">04</span>
|
||||||
<h2>Links</h2>
|
<h2>Links</h2>
|
||||||
</div>
|
</div>
|
||||||
<p class="block-subtitle">
|
<p class="block-subtitle">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
let stackList = [];
|
let stackList = [];
|
||||||
let projectsList = [];
|
let projectsList = [];
|
||||||
|
let workstationsList = [];
|
||||||
let linksList = [];
|
let linksList = [];
|
||||||
|
|
||||||
const fetchJson = async (path) => {
|
const fetchJson = async (path) => {
|
||||||
@@ -13,7 +14,7 @@ const fetchJson = async (path) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loadIcon = async (key) => {
|
const loadIcon = async (key) => {
|
||||||
const response = await fetch(`./icons/${key}.svg`);
|
const response = await fetch(`./img/icons/${key}.svg`);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return key;
|
return key;
|
||||||
@@ -25,5 +26,9 @@ const loadIcon = async (key) => {
|
|||||||
const formatIndex = (index) => String(index + 1).padStart(2, "0");
|
const formatIndex = (index) => String(index + 1).padStart(2, "0");
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
loadStack().then(loadProjects).then(loadLinks).catch(console.error);
|
loadStack()
|
||||||
|
.then(loadProjects)
|
||||||
|
.then(loadWorkstations)
|
||||||
|
.then(loadLinks)
|
||||||
|
.catch(console.error);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const loadProjects = async () => {
|
|||||||
|
|
||||||
const buildProjectCard = (project, index) => {
|
const buildProjectCard = (project, index) => {
|
||||||
const card = document.createElement("article");
|
const card = document.createElement("article");
|
||||||
card.classList.add("project-card", `project-card--${project.tone ?? "mint"}`);
|
card.classList.add("project-card", `tone-${project.tone ?? "mint"}`);
|
||||||
|
|
||||||
const header = document.createElement("div");
|
const header = document.createElement("div");
|
||||||
header.classList.add("project-card__header");
|
header.classList.add("project-card__header");
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
let isStackExpanded = false;
|
||||||
|
|
||||||
const getExperienceLevel = (years) => {
|
const getExperienceLevel = (years) => {
|
||||||
if (years >= 7) return "Core";
|
if (years >= 7) return "Core";
|
||||||
if (years >= 4) return "Strong";
|
if (years >= 4) return "Strong";
|
||||||
@@ -17,21 +19,34 @@ const loadStackForProject = (keys) => {
|
|||||||
|
|
||||||
const loadStack = async () => {
|
const loadStack = async () => {
|
||||||
const stackContainer = document.getElementById("stack");
|
const stackContainer = document.getElementById("stack");
|
||||||
|
const stackToggle = document.getElementById("stack-toggle");
|
||||||
|
|
||||||
if (!stackContainer) {
|
if (!stackContainer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stackList = await fetchJson("./data/stack.json");
|
stackList = await fetchJson("./data/stack.json");
|
||||||
const stackCards = stackList.map(buildStackCard).filter(Boolean);
|
renderStack(stackContainer);
|
||||||
|
|
||||||
|
if (stackToggle && stackList.some((stack) => stack.hide === true)) {
|
||||||
|
stackToggle.hidden = false;
|
||||||
|
stackToggle.addEventListener("click", () => {
|
||||||
|
isStackExpanded = !isStackExpanded;
|
||||||
|
stackToggle.textContent = isStackExpanded ? "Show less" : "View all";
|
||||||
|
stackToggle.setAttribute("aria-expanded", String(isStackExpanded));
|
||||||
|
renderStack(stackContainer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderStack = (stackContainer) => {
|
||||||
|
const stackCards = stackList
|
||||||
|
.filter((stack) => isStackExpanded || stack.hide !== true)
|
||||||
|
.map(buildStackCard);
|
||||||
stackContainer.replaceChildren(...stackCards);
|
stackContainer.replaceChildren(...stackCards);
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildStackCard = (stack) => {
|
const buildStackCard = (stack) => {
|
||||||
if (stack?.hide === true) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const card = document.createElement("div");
|
const card = document.createElement("div");
|
||||||
card.classList.add("stack-card", `tone-${stack.tone ?? "mint"}`);
|
card.classList.add("stack-card", `tone-${stack.tone ?? "mint"}`);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
let areWorkstationsExpanded = false;
|
||||||
|
|
||||||
|
const loadWorkstations = async () => {
|
||||||
|
const workstationContainer = document.getElementById("workstations");
|
||||||
|
const workstationToggle = document.getElementById("workstation-toggle");
|
||||||
|
|
||||||
|
if (!workstationContainer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
workstationsList = await fetchJson("./data/workstations.json");
|
||||||
|
renderWorkstations(workstationContainer);
|
||||||
|
|
||||||
|
if (
|
||||||
|
workstationToggle &&
|
||||||
|
workstationsList.some((workstation) => workstation.actual === false)
|
||||||
|
) {
|
||||||
|
workstationToggle.hidden = false;
|
||||||
|
workstationToggle.addEventListener("click", () => {
|
||||||
|
areWorkstationsExpanded = !areWorkstationsExpanded;
|
||||||
|
workstationToggle.textContent = areWorkstationsExpanded
|
||||||
|
? "Show less"
|
||||||
|
: "View all";
|
||||||
|
workstationToggle.setAttribute(
|
||||||
|
"aria-expanded",
|
||||||
|
String(areWorkstationsExpanded),
|
||||||
|
);
|
||||||
|
renderWorkstations(workstationContainer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderWorkstations = (workstationContainer) => {
|
||||||
|
const workstationCards = workstationsList
|
||||||
|
.filter(
|
||||||
|
(workstation) => areWorkstationsExpanded || workstation.actual !== false,
|
||||||
|
)
|
||||||
|
.map(buildWorkstationCard);
|
||||||
|
workstationContainer.replaceChildren(...workstationCards);
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildWorkstationCard = (workstation, index) => {
|
||||||
|
const card = document.createElement("article");
|
||||||
|
card.classList.add("workstation-card", `tone-${workstation.tone ?? "mint"}`);
|
||||||
|
|
||||||
|
const header = document.createElement("div");
|
||||||
|
header.classList.add("workstation-card__header");
|
||||||
|
|
||||||
|
const indexBadge = document.createElement("span");
|
||||||
|
indexBadge.classList.add("workstation-card__index");
|
||||||
|
indexBadge.textContent = formatIndex(index);
|
||||||
|
|
||||||
|
const key = document.createElement("span");
|
||||||
|
key.classList.add("workstation-card__key");
|
||||||
|
key.textContent = workstation.key;
|
||||||
|
|
||||||
|
const status = document.createElement("span");
|
||||||
|
status.classList.add(
|
||||||
|
"workstation-card__status",
|
||||||
|
workstation.actual
|
||||||
|
? "workstation-card__status--actual"
|
||||||
|
: "workstation-card__status--archive",
|
||||||
|
);
|
||||||
|
status.textContent = workstation.actual ? "active" : "archive";
|
||||||
|
|
||||||
|
const title = document.createElement("h3");
|
||||||
|
title.classList.add("workstation-card__title");
|
||||||
|
title.textContent = workstation.name;
|
||||||
|
|
||||||
|
const specs = document.createElement("dl");
|
||||||
|
specs.classList.add("workstation-card__specs");
|
||||||
|
|
||||||
|
appendSpec(specs, "CPU", workstation.specs?.cpu);
|
||||||
|
appendSpec(specs, "GPU", workstation.specs?.gpu);
|
||||||
|
appendSpec(specs, "RAM", workstation.specs?.ram);
|
||||||
|
appendSpec(specs, "OS", workstation.specs?.os);
|
||||||
|
|
||||||
|
const storage = buildChipGroup(
|
||||||
|
"Storage",
|
||||||
|
workstation.specs?.storage?.map(formatStorage) ?? [],
|
||||||
|
);
|
||||||
|
const devices = buildChipGroup(
|
||||||
|
"Devices",
|
||||||
|
workstation.devices?.map((device) => device.name) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
header.append(indexBadge, key, status);
|
||||||
|
card.append(header, title, specs);
|
||||||
|
|
||||||
|
if (storage) {
|
||||||
|
card.append(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices) {
|
||||||
|
card.append(devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
return card;
|
||||||
|
};
|
||||||
|
|
||||||
|
const appendSpec = (list, label, value) => {
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const term = document.createElement("dt");
|
||||||
|
term.textContent = label;
|
||||||
|
|
||||||
|
const description = document.createElement("dd");
|
||||||
|
description.textContent = value;
|
||||||
|
|
||||||
|
list.append(term, description);
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildChipGroup = (label, items) => {
|
||||||
|
if (items.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const group = document.createElement("div");
|
||||||
|
group.classList.add("workstation-card__group");
|
||||||
|
|
||||||
|
const title = document.createElement("p");
|
||||||
|
title.classList.add("workstation-card__group-title");
|
||||||
|
title.textContent = label;
|
||||||
|
|
||||||
|
const chips = document.createElement("div");
|
||||||
|
chips.classList.add("workstation-card__chips");
|
||||||
|
chips.append(
|
||||||
|
...items.map((item) => {
|
||||||
|
const chip = document.createElement("span");
|
||||||
|
chip.textContent = item;
|
||||||
|
return chip;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
group.append(title, chips);
|
||||||
|
return group;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatStorage = (storage) => {
|
||||||
|
const parts = [storage.capacity, storage.name, storage.type].filter(Boolean);
|
||||||
|
return parts.join(" · ");
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"background_color": "#1f1f28",
|
||||||
|
"description": "Go and JavaScript developer building self-hosted tools, small web systems, and developer-focused projects.",
|
||||||
|
"display": "standalone",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"sizes": "512x512",
|
||||||
|
"src": "icons/favicon-512.png",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "ScuroNeko",
|
||||||
|
"scope": "/",
|
||||||
|
"short_name": "ScuroNeko",
|
||||||
|
"start_url": "/",
|
||||||
|
"theme_color": "#1f1f28"
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
border-color: var(--card-accent);
|
border-color: var(--card-accent);
|
||||||
background-color: color-mix(in srgb, var(--card-glow) 36%, var(--surface));
|
background-color: color-mix(in srgb, var(--card-glow) 36%, var(--surface));
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-card__index {
|
.link-card__index {
|
||||||
@@ -64,8 +64,9 @@
|
|||||||
.link-card__name {
|
.link-card__name {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-family: "Barlow Condensed", sans-serif;
|
font-family: "Barlow Condensed", sans-serif;
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-card__label {
|
.link-card__label {
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
--glow-cyan: rgba(127, 180, 202, 0.2);
|
--glow-cyan: rgba(127, 180, 202, 0.2);
|
||||||
--glow-green: rgba(152, 187, 108, 0.18);
|
--glow-green: rgba(152, 187, 108, 0.18);
|
||||||
--glow-pink: rgba(210, 126, 153, 0.18);
|
--glow-pink: rgba(210, 126, 153, 0.18);
|
||||||
|
--glow-teal: rgba(107, 196, 180, 0.18);
|
||||||
|
--glow-lime: rgba(184, 204, 100, 0.18);
|
||||||
|
--glow-rose: rgba(224, 112, 128, 0.2);
|
||||||
|
|
||||||
--block-size: 980px;
|
--block-size: 980px;
|
||||||
|
|
||||||
@@ -64,15 +67,18 @@ a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 3.5rem;
|
font-size: clamp(3.5rem, 7vw, 5rem);
|
||||||
|
line-height: 0.95;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 2rem;
|
font-size: clamp(1.85rem, 3vw, 2.25rem);
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
@@ -124,46 +130,6 @@ h6 {
|
|||||||
max-width: 560px;
|
max-width: 560px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tone-blue {
|
|
||||||
--card-accent: var(--primary);
|
|
||||||
--card-glow: var(--glow-blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-gold {
|
|
||||||
--card-accent: var(--warm);
|
|
||||||
--card-glow: var(--glow-gold);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-mint {
|
|
||||||
--card-accent: var(--accent);
|
|
||||||
--card-glow: var(--glow-mint);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-purple {
|
|
||||||
--card-accent: #b876d3;
|
|
||||||
--card-glow: var(--glow-purple);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-red {
|
|
||||||
--card-accent: var(--danger);
|
|
||||||
--card-glow: var(--glow-red);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-cyan {
|
|
||||||
--card-accent: #7fb4ca;
|
|
||||||
--card-glow: var(--glow-cyan);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-green {
|
|
||||||
--card-accent: #98bb6c;
|
|
||||||
--card-glow: var(--glow-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tone-pink {
|
|
||||||
--card-accent: #d27e99;
|
|
||||||
--card-glow: var(--glow-pink);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 560px) {
|
@media (max-width: 560px) {
|
||||||
body {
|
body {
|
||||||
padding-top: 32px;
|
padding-top: 32px;
|
||||||
|
|||||||
@@ -1,43 +1,3 @@
|
|||||||
.project-card.project-card--blue {
|
|
||||||
--project-accent: var(--primary);
|
|
||||||
--project-glow: var(--glow-blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--gold {
|
|
||||||
--project-accent: var(--warm);
|
|
||||||
--project-glow: var(--glow-gold);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--mint {
|
|
||||||
--project-accent: var(--accent);
|
|
||||||
--project-glow: var(--glow-mint);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--purple {
|
|
||||||
--project-accent: #b876d3;
|
|
||||||
--project-glow: var(--glow-purple);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--red {
|
|
||||||
--project-accent: var(--danger);
|
|
||||||
--project-glow: var(--glow-red);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--cyan {
|
|
||||||
--project-accent: #7fb4ca;
|
|
||||||
--project-glow: var(--glow-cyan);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--green {
|
|
||||||
--project-accent: #98bb6c;
|
|
||||||
--project-glow: var(--glow-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card.project-card--pink {
|
|
||||||
--project-accent: #d27e99;
|
|
||||||
--project-glow: var(--glow-pink);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-grid {
|
.project-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
@@ -46,16 +6,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.project-card {
|
.project-card {
|
||||||
--project-accent: var(--accent);
|
|
||||||
--project-glow: var(--glow-mint);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 220px;
|
min-height: 220px;
|
||||||
padding: 22px;
|
padding: 22px;
|
||||||
border: 1px solid color-mix(in srgb, var(--project-accent) 36%, var(--border));
|
border: 1px solid color-mix(in srgb, var(--card-accent) 36%, var(--border));
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background:
|
background:
|
||||||
linear-gradient(140deg, var(--project-glow), transparent 48%),
|
linear-gradient(140deg, var(--card-glow), transparent 48%),
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent),
|
linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent),
|
||||||
var(--surface);
|
var(--surface);
|
||||||
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.2);
|
||||||
@@ -66,9 +24,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.project-card:hover {
|
.project-card:hover {
|
||||||
border-color: var(--project-accent);
|
border-color: var(--card-accent);
|
||||||
box-shadow: 0 24px 52px rgba(0, 0, 0, 0.28);
|
box-shadow: 0 24px 52px rgba(0, 0, 0, 0.28);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-card__header {
|
.project-card__header {
|
||||||
@@ -92,8 +50,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.project-card__key {
|
.project-card__key {
|
||||||
border: 1px solid color-mix(in srgb, var(--project-accent) 56%, var(--border));
|
border: 1px solid color-mix(in srgb, var(--card-accent) 56%, var(--border));
|
||||||
color: var(--project-accent);
|
color: var(--card-accent);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +65,8 @@
|
|||||||
.project-card__title {
|
.project-card__title {
|
||||||
margin-top: 22px;
|
margin-top: 22px;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-size: 1.75rem;
|
font-size: clamp(1.6rem, 2.4vw, 1.9rem);
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-card__description {
|
.project-card__description {
|
||||||
@@ -131,6 +90,7 @@
|
|||||||
color: var(--card-accent);
|
color: var(--card-accent);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-family: var(--fonts-monospace);
|
font-family: var(--fonts-monospace);
|
||||||
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-card__links {
|
.project-card__links {
|
||||||
@@ -144,7 +104,7 @@
|
|||||||
|
|
||||||
.project-card__links a {
|
.project-card__links a {
|
||||||
border-bottom: 1px solid currentColor;
|
border-bottom: 1px solid currentColor;
|
||||||
color: var(--project-accent);
|
color: var(--card-accent);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,32 @@
|
|||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stack-toggle {
|
||||||
|
margin-top: 14px;
|
||||||
|
min-height: 38px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
transition:
|
||||||
|
background-color 160ms ease,
|
||||||
|
border-color 160ms ease,
|
||||||
|
color 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-toggle:hover {
|
||||||
|
border-color: var(--accent);
|
||||||
|
background-color: var(--glow-mint);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-toggle[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.stack-card {
|
.stack-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -30,7 +56,7 @@
|
|||||||
.stack-card:hover {
|
.stack-card:hover {
|
||||||
border-color: var(--card-accent);
|
border-color: var(--card-accent);
|
||||||
box-shadow: 0 20px 44px rgba(0, 0, 0, 0.26);
|
box-shadow: 0 20px 44px rgba(0, 0, 0, 0.26);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack-card__badge {
|
.stack-card__badge {
|
||||||
@@ -70,6 +96,8 @@
|
|||||||
.stack-card__title {
|
.stack-card__title {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack-card__footer {
|
.stack-card__footer {
|
||||||
@@ -88,6 +116,7 @@
|
|||||||
border: 1px solid rgba(220, 215, 186, 0.16);
|
border: 1px solid rgba(220, 215, 186, 0.16);
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
background-color: rgba(31, 31, 40, 0.4);
|
background-color: rgba(31, 31, 40, 0.4);
|
||||||
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 780px) {
|
@media (max-width: 780px) {
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--bg: #f2ecbc;
|
||||||
|
--surface: #e5ddb0;
|
||||||
|
--border: #c8c093;
|
||||||
|
|
||||||
|
--text: #545464;
|
||||||
|
--text-soft: #43436c;
|
||||||
|
--text-muted: #77713f;
|
||||||
|
|
||||||
|
--primary: #2f5d95;
|
||||||
|
--accent: #4e8ca2;
|
||||||
|
--warm: #cc6d00;
|
||||||
|
--danger: #c84053;
|
||||||
|
--glow-blue: rgba(47, 93, 149, 0.14);
|
||||||
|
--glow-gold: rgba(204, 109, 0, 0.13);
|
||||||
|
--glow-mint: rgba(78, 140, 162, 0.12);
|
||||||
|
--glow-purple: rgba(118, 107, 144, 0.14);
|
||||||
|
--glow-red: rgba(200, 64, 83, 0.13);
|
||||||
|
--glow-cyan: rgba(58, 143, 183, 0.12);
|
||||||
|
--glow-green: rgba(111, 137, 78, 0.13);
|
||||||
|
--glow-pink: rgba(179, 91, 121, 0.12);
|
||||||
|
--glow-teal: rgba(90, 119, 133, 0.12);
|
||||||
|
--glow-lime: rgba(119, 113, 63, 0.12);
|
||||||
|
--glow-rose: rgba(215, 71, 75, 0.13);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-purple {
|
||||||
|
--card-accent: #766b90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-cyan {
|
||||||
|
--card-accent: #3a8fb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-green {
|
||||||
|
--card-accent: #6f894e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-pink {
|
||||||
|
--card-accent: #b35b79;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-teal {
|
||||||
|
--card-accent: #5a7785;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-lime {
|
||||||
|
--card-accent: #77713f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-rose {
|
||||||
|
--card-accent: #d7474b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card,
|
||||||
|
.project-card,
|
||||||
|
.workstation-card {
|
||||||
|
background:
|
||||||
|
linear-gradient(135deg, var(--card-glow), transparent 46%),
|
||||||
|
linear-gradient(180deg, rgba(247, 241, 197, 0.52), transparent),
|
||||||
|
var(--surface);
|
||||||
|
box-shadow: 0 16px 36px rgba(67, 67, 108, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card:hover,
|
||||||
|
.project-card:hover,
|
||||||
|
.workstation-card:hover {
|
||||||
|
box-shadow: 0 22px 48px rgba(67, 67, 108, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack-card__badge,
|
||||||
|
.stack-card__footer span,
|
||||||
|
.project-card__status,
|
||||||
|
.project-card__stack span,
|
||||||
|
.workstation-card__status,
|
||||||
|
.workstation-card__specs dt,
|
||||||
|
.workstation-card__chips span,
|
||||||
|
.link-card {
|
||||||
|
background-color: rgba(242, 236, 188, 0.58);
|
||||||
|
border-color: color-mix(in srgb, var(--card-accent) 28%, var(--border));
|
||||||
|
}
|
||||||
|
.workstation-card__status--actual {
|
||||||
|
background-color: var(--card-accent);
|
||||||
|
color: var(--surface);
|
||||||
|
}
|
||||||
|
.workstation-card__status--archive {
|
||||||
|
background-color: rgba(31, 31, 40, 0.52);
|
||||||
|
color: var(--surface);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card:hover {
|
||||||
|
background-color: color-mix(in srgb, var(--card-glow) 46%, var(--surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-pill,
|
||||||
|
.site-nav a,
|
||||||
|
.stack-toggle,
|
||||||
|
.workstation-toggle {
|
||||||
|
background-color: rgba(242, 236, 188, 0.42);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
.tone-blue {
|
||||||
|
--card-accent: var(--primary);
|
||||||
|
--card-glow: var(--glow-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-gold {
|
||||||
|
--card-accent: var(--warm);
|
||||||
|
--card-glow: var(--glow-gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-mint {
|
||||||
|
--card-accent: var(--accent);
|
||||||
|
--card-glow: var(--glow-mint);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-purple {
|
||||||
|
--card-accent: #b876d3;
|
||||||
|
--card-glow: var(--glow-purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-red {
|
||||||
|
--card-accent: var(--danger);
|
||||||
|
--card-glow: var(--glow-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-cyan {
|
||||||
|
--card-accent: #7fb4ca;
|
||||||
|
--card-glow: var(--glow-cyan);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-green {
|
||||||
|
--card-accent: #98bb6c;
|
||||||
|
--card-glow: var(--glow-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-pink {
|
||||||
|
--card-accent: #d27e99;
|
||||||
|
--card-glow: var(--glow-pink);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-teal {
|
||||||
|
--card-accent: #6bc4b4;
|
||||||
|
--card-glow: var(--glow-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-lime {
|
||||||
|
--card-accent: #b8cc64;
|
||||||
|
--card-glow: var(--glow-lime);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-rose {
|
||||||
|
--card-accent: #e07080;
|
||||||
|
--card-glow: var(--glow-rose);
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
.workstation-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 18px;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-toggle {
|
||||||
|
margin-top: 14px;
|
||||||
|
min-height: 38px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
transition:
|
||||||
|
background-color 160ms ease,
|
||||||
|
border-color 160ms ease,
|
||||||
|
color 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-toggle:hover {
|
||||||
|
border-color: var(--accent);
|
||||||
|
background-color: var(--glow-mint);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-toggle[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 260px;
|
||||||
|
padding: 22px;
|
||||||
|
border: 1px solid color-mix(in srgb, var(--card-accent) 36%, var(--border));
|
||||||
|
border-radius: 8px;
|
||||||
|
background:
|
||||||
|
linear-gradient(140deg, var(--card-glow), transparent 48%),
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent),
|
||||||
|
var(--surface);
|
||||||
|
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.2);
|
||||||
|
transition:
|
||||||
|
border-color 160ms ease,
|
||||||
|
transform 160ms ease,
|
||||||
|
box-shadow 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card:hover {
|
||||||
|
border-color: var(--card-accent);
|
||||||
|
box-shadow: 0 24px 52px rgba(0, 0, 0, 0.28);
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__index {
|
||||||
|
color: var(--text-soft);
|
||||||
|
font-family: var(--fonts-monospace);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__key,
|
||||||
|
.workstation-card__status {
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-family: var(--fonts-monospace);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__key {
|
||||||
|
border: 1px solid color-mix(in srgb, var(--card-accent) 56%, var(--border));
|
||||||
|
color: var(--card-accent);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__status {
|
||||||
|
margin-left: auto;
|
||||||
|
background-color: rgba(31, 31, 40, 0.52);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.workstation-card__status--actual {
|
||||||
|
background-color: var(--card-accent);
|
||||||
|
color: var(--surface);
|
||||||
|
}
|
||||||
|
.workstation-card__status--archive {
|
||||||
|
background-color: rgba(31, 31, 40, 0.52);
|
||||||
|
color: var(--text);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__title {
|
||||||
|
margin-top: 22px;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: clamp(1.6rem, 2.4vw, 1.9rem);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__specs {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 68px minmax(0, 1fr);
|
||||||
|
gap: 8px 12px;
|
||||||
|
margin-top: 18px;
|
||||||
|
font-family: var(--fonts-monospace);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__specs dt {
|
||||||
|
align-self: start;
|
||||||
|
border: 1px solid color-mix(in srgb, var(--card-accent) 48%, var(--border));
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 4px 7px;
|
||||||
|
background-color: rgba(31, 31, 40, 0.36);
|
||||||
|
color: var(--card-accent);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__specs dd {
|
||||||
|
align-self: center;
|
||||||
|
min-width: 0;
|
||||||
|
color: var(--text);
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__group {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__group-title {
|
||||||
|
color: var(--card-accent);
|
||||||
|
font-family: var(--fonts-monospace);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__chips {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__chips span {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--card-glow);
|
||||||
|
padding: 5px 9px;
|
||||||
|
background-color: rgba(31, 31, 40, 0.42);
|
||||||
|
color: var(--card-accent);
|
||||||
|
font-family: var(--fonts-monospace);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 780px) {
|
||||||
|
.workstation-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 560px) {
|
||||||
|
.workstation-card__specs {
|
||||||
|
grid-template-columns: 58px minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-card__specs dd {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||