workstations and light theme
@@ -2,6 +2,10 @@
|
||||
{
|
||||
"description": "A personal page for projects, stack notes, and developer work.",
|
||||
"key": "web",
|
||||
"links": {
|
||||
"homepage": "https://scuroneko.dev",
|
||||
"sources": "https://git.scuroneko.dev/ScuroNeko/scuroneko.dev"
|
||||
},
|
||||
"name": "ScuroNeko.dev",
|
||||
"stack": ["html", "css", "js"],
|
||||
"status": "active",
|
||||
@@ -16,6 +20,6 @@
|
||||
"name": "Laniakea",
|
||||
"stack": ["go", "tg"],
|
||||
"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",
|
||||
"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,
|
||||
"key": "html",
|
||||
@@ -65,5 +79,12 @@
|
||||
"name": "JavaScript",
|
||||
"tone": "gold",
|
||||
"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>
|
||||
<meta charset="UTF-8" />
|
||||
<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/hero.css" />
|
||||
<link rel="stylesheet" href="./styles/stack.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/tones.css" />
|
||||
<link rel="stylesheet" href="./styles/theme-light.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
@@ -18,11 +57,13 @@
|
||||
rel="stylesheet"
|
||||
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/stack.js" defer></script>
|
||||
<script src="./js/projects.js" defer></script>
|
||||
<script src="./js/workstations.js" defer></script>
|
||||
<script src="./js/links.js" defer></script>
|
||||
<title>ScuroNeko</title>
|
||||
</head>
|
||||
@@ -38,6 +79,7 @@
|
||||
<nav class="site-nav" aria-label="Page sections">
|
||||
<a href="#stack-section">Stack</a>
|
||||
<a href="#projects-section">Projects</a>
|
||||
<a href="#workstations-section">Workstations</a>
|
||||
<a href="#links-section">Links</a>
|
||||
</nav>
|
||||
</div>
|
||||
@@ -51,6 +93,9 @@
|
||||
<p class="block-subtitle">
|
||||
Tools I reach for when the task needs to ship.
|
||||
</p>
|
||||
<button class="stack-toggle" id="stack-toggle" type="button" hidden>
|
||||
View all
|
||||
</button>
|
||||
<div class="stack-grid" id="stack"></div>
|
||||
</section>
|
||||
|
||||
@@ -63,9 +108,26 @@
|
||||
<div class="project-grid" id="projects"></div>
|
||||
</section>
|
||||
|
||||
<section class="block" id="links-section">
|
||||
<section class="block" id="workstations-section">
|
||||
<div class="section-heading">
|
||||
<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>
|
||||
</div>
|
||||
<p class="block-subtitle">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
let stackList = [];
|
||||
let projectsList = [];
|
||||
let workstationsList = [];
|
||||
let linksList = [];
|
||||
|
||||
const fetchJson = async (path) => {
|
||||
@@ -13,7 +14,7 @@ const fetchJson = async (path) => {
|
||||
};
|
||||
|
||||
const loadIcon = async (key) => {
|
||||
const response = await fetch(`./icons/${key}.svg`);
|
||||
const response = await fetch(`./img/icons/${key}.svg`);
|
||||
|
||||
if (!response.ok) {
|
||||
return key;
|
||||
@@ -25,5 +26,9 @@ const loadIcon = async (key) => {
|
||||
const formatIndex = (index) => String(index + 1).padStart(2, "0");
|
||||
|
||||
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 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");
|
||||
header.classList.add("project-card__header");
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
let isStackExpanded = false;
|
||||
|
||||
const getExperienceLevel = (years) => {
|
||||
if (years >= 7) return "Core";
|
||||
if (years >= 4) return "Strong";
|
||||
@@ -17,21 +19,34 @@ const loadStackForProject = (keys) => {
|
||||
|
||||
const loadStack = async () => {
|
||||
const stackContainer = document.getElementById("stack");
|
||||
const stackToggle = document.getElementById("stack-toggle");
|
||||
|
||||
if (!stackContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
const buildStackCard = (stack) => {
|
||||
if (stack?.hide === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const card = document.createElement("div");
|
||||
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);
|
||||
background-color: color-mix(in srgb, var(--card-glow) 36%, var(--surface));
|
||||
color: var(--text);
|
||||
transform: translateY(-2px);
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.link-card__index {
|
||||
@@ -64,8 +64,9 @@
|
||||
.link-card__name {
|
||||
color: var(--text);
|
||||
font-family: "Barlow Condensed", sans-serif;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.link-card__label {
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
--glow-cyan: rgba(127, 180, 202, 0.2);
|
||||
--glow-green: rgba(152, 187, 108, 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;
|
||||
|
||||
@@ -64,15 +67,18 @@ a:hover {
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.5rem;
|
||||
font-size: clamp(3.5rem, 7vw, 5rem);
|
||||
line-height: 0.95;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
font-size: clamp(1.85rem, 3vw, 2.25rem);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@@ -124,46 +130,6 @@ h6 {
|
||||
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) {
|
||||
body {
|
||||
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 {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
@@ -46,16 +6,14 @@
|
||||
}
|
||||
|
||||
.project-card {
|
||||
--project-accent: var(--accent);
|
||||
--project-glow: var(--glow-mint);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 220px;
|
||||
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;
|
||||
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),
|
||||
var(--surface);
|
||||
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.2);
|
||||
@@ -66,9 +24,9 @@
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
border-color: var(--project-accent);
|
||||
border-color: var(--card-accent);
|
||||
box-shadow: 0 24px 52px rgba(0, 0, 0, 0.28);
|
||||
transform: translateY(-2px);
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.project-card__header {
|
||||
@@ -92,8 +50,8 @@
|
||||
}
|
||||
|
||||
.project-card__key {
|
||||
border: 1px solid color-mix(in srgb, var(--project-accent) 56%, var(--border));
|
||||
color: var(--project-accent);
|
||||
border: 1px solid color-mix(in srgb, var(--card-accent) 56%, var(--border));
|
||||
color: var(--card-accent);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@@ -107,7 +65,8 @@
|
||||
.project-card__title {
|
||||
margin-top: 22px;
|
||||
color: var(--text);
|
||||
font-size: 1.75rem;
|
||||
font-size: clamp(1.6rem, 2.4vw, 1.9rem);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.project-card__description {
|
||||
@@ -131,6 +90,7 @@
|
||||
color: var(--card-accent);
|
||||
font-size: 0.9rem;
|
||||
font-family: var(--fonts-monospace);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.project-card__links {
|
||||
@@ -144,7 +104,7 @@
|
||||
|
||||
.project-card__links a {
|
||||
border-bottom: 1px solid currentColor;
|
||||
color: var(--project-accent);
|
||||
color: var(--card-accent);
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,32 @@
|
||||
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 {
|
||||
position: relative;
|
||||
display: grid;
|
||||
@@ -30,7 +56,7 @@
|
||||
.stack-card:hover {
|
||||
border-color: var(--card-accent);
|
||||
box-shadow: 0 20px 44px rgba(0, 0, 0, 0.26);
|
||||
transform: translateY(-2px);
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.stack-card__badge {
|
||||
@@ -70,6 +96,8 @@
|
||||
.stack-card__title {
|
||||
margin-top: 4px;
|
||||
color: var(--text);
|
||||
font-size: 1.5rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.stack-card__footer {
|
||||
@@ -88,6 +116,7 @@
|
||||
border: 1px solid rgba(220, 215, 186, 0.16);
|
||||
padding: 4px 8px;
|
||||
background-color: rgba(31, 31, 40, 0.4);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||