cursors and links

This commit is contained in:
Clove 2026-06-15 09:01:18 +01:00
parent e8c63b1de5
commit 133384466d
48 changed files with 121 additions and 50 deletions

BIN
assets/cursor/alias_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/cursor/cell_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/cursor/copy_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/cursor/default_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/cursor/draft_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/cursor/help_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/cursor/no-drop_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/cursor/pencil_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/cursor/pirate_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/cursor/pointer_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/cursor/text_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/cursor/zoom-in_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -30,6 +30,7 @@
============================================================ */ ============================================================ */
* { * {
box-sizing: border-box; box-sizing: border-box;
cursor: url('/assets/cursor/default_0.png') 3 3, auto;
} }
/* Smooth cross-fade between pages */ /* Smooth cross-fade between pages */
@ -74,6 +75,48 @@ body {
color: var(--text); color: var(--text);
} }
/* clickable */
a, button, [role="button"], label[for], select, summary {
cursor: url('../assets/cursor/pointer_0.png'), pointer;
}
/* text entry / editing */
input:not([type="button"]):not([type="submit"]):not([type="checkbox"]):not([type="radio"]),
textarea, [contenteditable="true"] {
cursor: url('../assets/cursor/text_0.png'), text;
}
/* loading */
[aria-busy="true"], .is-loading {
cursor: url('../assets/cursor/wait_0.png'), wait;
}
/* busy but interactive */
.is-progress {
cursor: url('../assets/cursor/progress_0.png'), progress;
}
/* help */
[title]:not(a):not(button), .help {
cursor: url('../assets/cursor/help_0.png'), help;
}
/* disabled */
:disabled, [disabled], [aria-disabled="true"] {
cursor: url('../assets/cursor/not-allowed_0.png'), not-allowed;
}
/* draggable */
[draggable="true"] {
cursor: url('../assets/cursor/openhand_0.png'), grab;
}
/* crosshair / zoom (if you use them) */
.crosshair { cursor: url('../assets/cursor/crosshair_0.png'), crosshair; }
.zoom-in { cursor: url('../assets/cursor/zoom-in_0.png'), zoom-in; }
.zoom-out { cursor: url('../assets/cursor/zoom-out_0.png'), zoom-out; }
/* Estrogen watermark blended into the background */ /* Estrogen watermark blended into the background */
body::before { body::before {
content: ""; content: "";
@ -1768,6 +1811,11 @@ details.waka-section[open]>summary.section-title::after {
} }
/* ---- hardware spec list ---- */ /* ---- hardware spec list ---- */
.hw-item {
text-decoration: none;
color: var(--text);
}
.hw-intro { .hw-intro {
margin: 0 0 0.9rem; margin: 0 0 0.9rem;
font-size: 0.8rem; font-size: 0.8rem;
@ -2360,6 +2408,7 @@ body:has(.music-wrap) {
padding: 1.1rem; padding: 1.1rem;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
text-decoration: none;
} }
/* a soft wash of the album accent behind the hero */ /* a soft wash of the album accent behind the hero */
@ -2420,30 +2469,6 @@ body:has(.music-wrap) {
color: rgb(var(--accent-rgb)); color: rgb(var(--accent-rgb));
} }
#music.is-live .mnp-state::before {
content: "";
width: 7px;
height: 7px;
border-radius: 50%;
background: rgb(var(--accent-rgb));
box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.6);
animation: np-pulse 2s infinite;
}
@keyframes np-pulse {
0% {
box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.5);
}
70% {
box-shadow: 0 0 0 7px rgba(var(--accent-rgb), 0);
}
100% {
box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0);
}
}
.mnp-title { .mnp-title {
display: block; display: block;
font-size: 1.3rem; font-size: 1.3rem;
@ -2541,13 +2566,24 @@ body:has(.music-wrap) {
transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease; transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
} }
.ly-lock::before { /* Spotify-style equalizer bars (replaces the old status dot) */
content: ""; .ly-bars {
width: 7px; display: inline-flex;
height: 7px; align-items: flex-end;
border-radius: 50%; gap: 2px;
width: 13px;
height: 11px;
flex-shrink: 0;
}
.ly-bars i {
flex: 1;
height: 100%;
border-radius: 1px;
background: currentColor; background: currentColor;
opacity: 0.6; transform-origin: bottom;
transform: scaleY(0.4);
opacity: 0.55;
} }
.ly-lock.is-locked { .ly-lock.is-locked {
@ -2556,8 +2592,40 @@ body:has(.music-wrap) {
background: rgba(var(--accent-rgb), 0.1); background: rgba(var(--accent-rgb), 0.1);
} }
.ly-lock.is-locked::before { .ly-lock.is-locked .ly-bars i {
opacity: 1; opacity: 1;
animation: ly-eq 0.9s ease-in-out infinite;
}
.ly-lock.is-locked .ly-bars i:nth-child(2) {
animation-delay: 0.15s;
}
.ly-lock.is-locked .ly-bars i:nth-child(3) {
animation-delay: 0.3s;
}
.ly-lock.is-locked .ly-bars i:nth-child(4) {
animation-delay: 0.45s;
}
@keyframes ly-eq {
0%,
100% {
transform: scaleY(0.3);
}
50% {
transform: scaleY(1);
}
}
@media (prefers-reduced-motion: reduce) {
.ly-lock.is-locked .ly-bars i {
animation: none;
transform: scaleY(0.65);
}
} }
.ly-lock:not(.is-locked):hover { .ly-lock:not(.is-locked):hover {
@ -2817,10 +2885,6 @@ body:has(.music-wrap) {
transition: none; transition: none;
} }
#music.is-live .mnp-state::before {
animation: none;
}
.ly-line { .ly-line {
transition: color 0.15s ease; transition: color 0.15s ease;
} }

View File

@ -142,51 +142,51 @@
<dl class="hw-list"> <dl class="hw-list">
<div class="hw-row"> <div class="hw-row">
<dt>CPU</dt> <dt>CPU</dt>
<dd>AMD Ryzen 9 9950x3d 4.3 GHz 16-Core Processor</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/Pk62FT/amd-ryzen-9-9950x3d-43-ghz-16-core-processor-100-100000719wof">AMD Ryzen 9 9950x3d 4.3 GHz 16-Core Processor</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>GPU</dt> <dt>GPU</dt>
<dd>XFX Speedster MERC 310 Black Edition Radeon RX 7900 XTX 24 GB Video Card</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/GtXJ7P/xfx-speedster-merc-310-black-edition-radeon-rx-7900-xtx-24-gb-video-card-rx-79xmercb9">XFX Speedster MERC 310 Black Edition Radeon RX 7900 XTX 24 GB Video Card</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>RAM</dt> <dt>RAM</dt>
<dd>Corsair Vengeance 64 GB (2 x 32 GB) DDR5-6000 CL40 Memory</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/LWVmP6/corsair-vengeance-64-gb-2-x-32-gb-ddr5-6000-cl40-memory-cmk64gx5m2b6000z40">Corsair Vengeance 64 GB (2 x 32 GB) DDR5-6000 CL40 Memory</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Storage</dt> <dt>Storage</dt>
<dd>2x 1 TB NVMe + 10TB HDD</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/YPKscf/acer-predator-gm7-1-tb-m2-2280-pcie-40-x4-nvme-solid-state-drive-bl9bwwr118">2x 1TB NVMe</a> + <a class="hw-item" href="https://uk.pcpartpicker.com/product/fmfhP6/seagate-exos-x14-12-tb-35-7200-rpm-internal-hard-drive-st12000nm0008">10TB HDD</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Motherboard</dt> <dt>Motherboard</dt>
<dd>Gigabyte B850M AORUS ELITE WIFI6E ICE Micro ATX AM5 Motherboard</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/Q8KnTW/gigabyte-b850m-aorus-elite-wifi6e-ice-micro-atx-am5-motherboard-b850m-aorus-elite-wifi6e-ice">Gigabyte B850M AORUS ELITE WIFI6E ICE Micro ATX AM5 Motherboard</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Cooling</dt> <dt>Cooling</dt>
<dd>Thermalright Aqua Elite V3 66.17 CFM Liquid CPU Cooler</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/YXFmP6/thermalright-aqua-elite-v3-6617-cfm-liquid-cpu-cooler-aqua-elite-360-white-v3">Thermalright Aqua Elite V3 66.17 CFM Liquid CPU Cooler</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Keyboard</dt> <dt>Keyboard</dt>
<dd>Akko Sakura Miku 5108B Plus</dd> <dd><a class="hw-item" href="https://en.akkogear.com/product/sakura-miku-5108b-plus-mechanical-keyboard/">Akko Sakura Miku 5108B Plus</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Mouse</dt> <dt>Mouse</dt>
<dd>Logitech G502 X Gaming Lightspeed Wireless</dd> <dd><a class="hw-item" href="https://www.logitechg.com/en-gb/shop/p/g502-x-plus-wireless-lightforce.910-006163">Logitech G502 X Gaming Lightspeed Wireless</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Monitor(s)</dt> <dt>Monitor(s)</dt>
<dd>Gigabyte G34WQCP 34.0" 3440 x 1440 180 Hz Curved Monitor</dd> <dd><a class="hw-item" href="https://uk.pcpartpicker.com/product/XpVfrH/gigabyte-g34wqcp-340-3440-x-1440-180-hz-curved-monitor-g34wqcp">Gigabyte G34WQCP 34.0" 3440 x 1440 180 Hz Curved Monitor</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Headphones</dt> <dt>Headphones</dt>
<dd>Yowu Cat Ear Headphones Hatsune Miku NX</dd> <dd><a class="hw-item" href="https://m.yowu.com/product/detail?sku=3588">Yowu Cat Ear Headphones Hatsune Miku NX</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>Microphone</dt> <dt>Microphone</dt>
<dd>Aokeo AK-60 USB Microphone</dd> <dd><a class="hw-item" href="https://amzn.eu/d/00FjYEzR">Aokeo AK-60 USB Microphone</a></dd>
</div> </div>
<div class="hw-row"> <div class="hw-row">
<dt>OS</dt> <dt>OS</dt>
<dd>Arch Linux | Windows 11</dd> <dd><a class="hw-item" href="https://archlinux.org/download/">Arch Linux</a> | <a class="hw-item" href="https://www.microsoft.com/en-us/software-download/windows11">Windows 11</a></dd>
</div> </div>
</dl> </dl>
</details> </details>

View File

@ -289,7 +289,14 @@ console.log(`
lockBtn.hidden = !show; lockBtn.hidden = !show;
lockBtn.classList.toggle("is-locked", locked); lockBtn.classList.toggle("is-locked", locked);
lockBtn.setAttribute("aria-pressed", String(locked)); lockBtn.setAttribute("aria-pressed", String(locked));
lockBtn.textContent = locked ? "Following" : "Resume"; let label = lockBtn.querySelector(".ly-lock-label");
if (!label) {
lockBtn.innerHTML =
'<span class="ly-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span>' +
'<span class="ly-lock-label"></span>';
label = lockBtn.querySelector(".ly-lock-label");
}
label.textContent = locked ? "Synced" : "Sync";
} }
function release() { // user took over the scroll function release() { // user took over the scroll
if (!locked) return; if (!locked) return;

View File

@ -40,7 +40,7 @@
<main class="music-wrap" id="music"> <main class="music-wrap" id="music">
<header class="music-head"> <header class="music-head">
<h1>Music</h1> <h1>Music</h1>
<p>What I'm listening to, live — with lyrics that follow along.</p> <p>What I'm listening to, with lyrics that follow along.</p>
</header> </header>
<!-- now playing --> <!-- now playing -->
@ -62,7 +62,7 @@
<!-- lyrics --> <!-- lyrics -->
<div class="sec-row"> <div class="sec-row">
<h2 class="sec-title">Lyrics</h2> <h2 class="sec-title">Lyrics</h2>
<button class="ly-lock is-locked" id="ly-lock" type="button" aria-pressed="true" hidden>Following</button> <button class="ly-lock is-locked" id="ly-lock" type="button" aria-pressed="true" hidden><span class="ly-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span><span class="ly-lock-label">Synced</span></button>
</div> </div>
<div class="lyrics is-empty" id="lyrics"><p class="ly-note">Waiting for a track…</p></div> <div class="lyrics is-empty" id="lyrics"><p class="ly-note">Waiting for a track…</p></div>