bring up to date

This commit is contained in:
Clove 2026-06-02 20:19:17 +01:00
parent 4b6f83cc17
commit 4b8ef9a78a
29 changed files with 983 additions and 542 deletions

View File

@ -6,7 +6,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clove Twilight - Changelog</title> <title>Clove Twilight - Changelog</title>
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg"> <link rel="stylesheet" href="/css/themes/mocha.css">
<link rel="stylesheet" href="/css/themes/macchiato.css">
<link rel="stylesheet" href="/css/themes/frappe.css">
<link rel="stylesheet" href="/css/themes/latte.css">
<script>try { var f = localStorage.getItem('ctpFlavor'); document.documentElement.setAttribute('data-flavor', ['mocha', 'macchiato', 'frappe', 'latte'].indexOf(f) >= 0 ? f : 'mocha'); } catch (e) { document.documentElement.setAttribute('data-flavor', 'mocha'); }</script>
<link rel="icon" type="image/svg+xml" href="/images/favicon/favicon.svg">
<!-- SEO Meta Tags --> <!-- SEO Meta Tags -->
<meta name="description" content="Changelog for clove.is-a.dev" /> <meta name="description" content="Changelog for clove.is-a.dev" />
@ -24,7 +29,7 @@
<meta name="theme-color" content="#f5c2e7" /> <meta name="theme-color" content="#f5c2e7" />
<!-- Open Graph / Discord / Facebook --> <!-- Open Graph / Discord / Facebook -->
<meta property="og:image" content="https://clove.is-a.dev/images/favicon.png" /> <meta property="og:image" content="https://clove.is-a.dev/images/favicon/favicon.png" />
<meta property="og:site_name" content="clove.is-a.dev" /> <meta property="og:site_name" content="clove.is-a.dev" />
<meta property="og:title" content="Clove Twilight | Changelog" /> <meta property="og:title" content="Clove Twilight | Changelog" />
<meta property="og:description" content="Changelog for Clove Twilight" /> <meta property="og:description" content="Changelog for Clove Twilight" />
@ -33,7 +38,7 @@
<meta property="og:locale" content="en_GB" /> <meta property="og:locale" content="en_GB" />
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:image" content="https://clove.is-a.dev/images/favicon.png" /> <meta name="twitter:image" content="https://clove.is-a.dev/images/favicon/favicon.png" />
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Clove Twilight | Changelog" /> <meta name="twitter:title" content="Clove Twilight | Changelog" />
<meta name="twitter:description" content="Changelog for Clove Twilight" /> <meta name="twitter:description" content="Changelog for Clove Twilight" />
@ -48,17 +53,23 @@
</header> </header>
<a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden> <a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden>
<img class="np-art" alt="" referrerpolicy="no-referrer"> <img class="np-art" alt="" referrerpolicy="no-referrer" crossorigin="anonymous">
<span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span> <span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
<span class="np-text"> <span class="np-text">
<span class="np-label">Now playing</span> <span class="np-head">
<span class="np-status" aria-hidden="true"></span>
<span class="np-status-label"></span>
<span class="np-label">Now playing</span>
</span>
<span class="np-track"></span> <span class="np-track"></span>
<span class="np-artist"></span> <span class="np-artist"></span>
<span class="np-progress" aria-hidden="true">
<span class="np-bar"><span class="np-fill"></span></span>
<span class="np-times"><span class="np-cur">0:00</span><span class="np-dur">0:00</span></span>
</span>
</span> </span>
</a> </a>
<a class="version-tag" data-href="/changelog" title="Changelog">v1.4.0</a>
<main class="hub"> <main class="hub">
<header class="hub-header"> <header class="hub-header">
<h1>Changelog</h1> <h1>Changelog</h1>
@ -68,7 +79,56 @@
<section class="changelog" aria-label="Update history"> <section class="changelog" aria-label="Update history">
<article class="release"> <article class="release">
<header class="release-head"> <header class="release-head">
<span class="release-version">v1.4.0</span> <span class="release-version">v1.6.1-beta</span>
<time class="release-date">2026-06-02</time>
</header>
<ul class="release-notes">
<li><span class="tag tag-add">Added</span> live "Now Playing" widget powered by Discord presence
via Lanyard — shows your Discord status (online · idle · dnd) next to the current Spotify
track, album art, and a live progress bar</li>
<li><span class="tag tag-add">Added</span> page-wide accent that follows the music — the album art
is snapped to the nearest Catppuccin accent and applied to your name, the nav, link-card
hovers, and the system badges, fading back to the theme pink when nothing's playing</li>
<li><span class="tag tag-change">Changed</span> retired the Last.fm now-playing widget in favour of
the Lanyard one (status + Spotify progress, all client-side — still fine on GitHub Pages)</li>
</ul>
</article>
<article class="release">
<header class="release-head">
<span class="release-version">v1.6.0-beta</span>
<time class="release-date">2026-06-01</time>
</header>
<ul class="release-notes">
<li><span class="tag tag-add">Added</span> Catppuccin theme switcher — the icon button in the
top-right corner cycles Mocha · Macchiato · Frappé · Latte; choice is remembered between
visits</li>
<li><span class="tag tag-add">Added</span> one official-palette CSS file per flavor</li>
<li><span class="tag tag-change">Changed</span> merged the oneko cat and its secret modes into a
single cat.js; dropped dead/duplicate code</li>
<li><span class="tag tag-change">Changed</span> removed the corner version tag — this changelog is
now reachable only via /changelog directly</li>
<li><span class="tag tag-change">Changed</span> doughmination is now the beta playground — features
bake here before graduating to clove.is-a.dev</li>
<li><span class="tag tag-change">Changed</span> </li>
</ul>
</article>
<article class="release">
<header class="release-head">
<span class="release-version">v1.5.0-rc</span>
<time class="release-date">2026-05-31</time>
</header>
<ul class="release-notes">
<li><span class="tag tag-add">Added</span> in badge to the corner to reference the opposing site
(clove|doughmination)</li>
<li><span class="tag tag-add">Added</span> Dusty Cat mode</li>
</ul>
</article>
<article class="release">
<header class="release-head">
<span class="release-version">v1.4.0-rc</span>
<time class="release-date">2026-05-30</time> <time class="release-date">2026-05-30</time>
</header> </header>
<ul class="release-notes"> <ul class="release-notes">
@ -83,7 +143,7 @@
<article class="release"> <article class="release">
<header class="release-head"> <header class="release-head">
<span class="release-version">v1.3.0</span> <span class="release-version">v1.3.0-rc</span>
<time class="release-date">2026-05-29</time> <time class="release-date">2026-05-29</time>
</header> </header>
<ul class="release-notes"> <ul class="release-notes">
@ -94,7 +154,7 @@
<article class="release"> <article class="release">
<header class="release-head"> <header class="release-head">
<span class="release-version">v1.2.0</span> <span class="release-version">v1.2.0-rc</span>
<time class="release-date">2026-05-29</time> <time class="release-date">2026-05-29</time>
</header> </header>
<ul class="release-notes"> <ul class="release-notes">
@ -106,7 +166,7 @@
<article class="release"> <article class="release">
<header class="release-head"> <header class="release-head">
<span class="release-version">v1.1.0</span> <span class="release-version">v1.1.0-rc</span>
<time class="release-date">2026-05-29</time> <time class="release-date">2026-05-29</time>
</header> </header>
<ul class="release-notes"> <ul class="release-notes">
@ -117,7 +177,7 @@
<article class="release"> <article class="release">
<header class="release-head"> <header class="release-head">
<span class="release-version">v1.0.0</span> <span class="release-version">v1.0.0-rc</span>
<time class="release-date">2026-05-29</time> <time class="release-date">2026-05-29</time>
</header> </header>
<ul class="release-notes"> <ul class="release-notes">
@ -129,7 +189,7 @@
<article class="release"> <article class="release">
<header class="release-head"> <header class="release-head">
<span class="release-version">v0.1.0</span> <span class="release-version">v0.1.0-rc</span>
<time class="release-date">2026-02-16</time> <time class="release-date">2026-02-16</time>
</header> </header>
<ul class="release-notes"> <ul class="release-notes">
@ -141,27 +201,28 @@
<aside class="badges" aria-label="System badges"> <aside class="badges" aria-label="System badges">
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/amd.svg" alt=""> <img class="badge-icon" src="/images/misc/amd.svg" alt="">
AMD Purist AMD Purist
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/arch.svg" alt=""> <img class="badge-icon" src="/images/misc/arch.svg" alt="">
I use arch btw I use arch btw
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/debian.svg" alt=""> <img class="badge-icon" src="/images/misc/debian.svg" alt="">
Debian Professional Debian Professional
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/apple.svg" alt=""> <img class="badge-icon" src="/images/misc/apple.svg" alt="">
Apple Ecosystem Enthusiast Apple Ecosystem Enthusiast
</span> </span>
</aside> </aside>
<script src="/js/cat.js" data-cat="/images/oneko.gif"></script> <script src="/js/cat.js" data-cat="/images/misc/oneko.gif"></script>
<script src="/js/nav.js"></script> <script src="/js/nav.js"></script>
<script src="/js/now-playing.js"></script> <script src="/js/now-playing.js"></script>
<script src="/js/cat-modes.js"></script> <script src="/js/flavors.js"></script>
<script src="/js/site-switcher.js"></script>
</body> </body>
</html> </html>

View File

@ -31,42 +31,6 @@
font-style: normal; font-style: normal;
} }
:root {
/* https://catppuccin.com/palette/ */
/* Catppuccin Mocha */
/* accents */
--rosewater: #f5e0dc;
--flamingo: #f2cdcd;
--pink: #f5c2e7;
--mauve: #cba6f7;
--red: #f38ba8;
--maroon: #eba0ac;
--peach: #fab387;
--yellow: #f9e2af;
--green: #a6e3a1;
--teal: #94e2d5;
--sky: #89dceb;
--saphire: #74c7ec;
--blue: #89b4fa;
/* a lovely new blue passport */
--lavender: #b4befe;
/* Text */
--text: #cdd6f4;
--subtext-0: #a6adc8;
--subtext-1: #bac2de;
--overlay-0: #6c7086;
--overlay-1: #7f849c;
--overlay-2: #9399b2;
--surface-0: #313244;
--surface-1: #45475a;
--surface-2: #585b70;
/* Backgrounds */
--base: #1e1e2e;
--mantle: #181825;
--crust: #11111b;
/* Is this the crusty crab? */
}
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
@ -96,6 +60,14 @@ body {
overflow: hidden; overflow: hidden;
} }
/* Gradient lives on <html> too, so it propagates to the page canvas.
On mobile (scrolling, URL-bar resize, overscroll) the area outside
the body would otherwise expose the root canvas white in the light
(latte) theme. Painting <html> keeps every theme's background filled. */
html {
background: linear-gradient(135deg, var(--base) 0%, var(--mantle) 60%, var(--crust) 100%);
}
body { body {
font-family: 'Comic Code', sans-serif; font-family: 'Comic Code', sans-serif;
display: flex; display: flex;
@ -114,7 +86,7 @@ body::before {
content: ""; content: "";
position: fixed; position: fixed;
inset: 0; inset: 0;
background: url(/images/estrogen.svg) center / cover no-repeat; background: url(/images/theme/estrogen.svg) center / cover no-repeat;
filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%); filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%);
opacity: 0.05; opacity: 0.05;
pointer-events: none; pointer-events: none;
@ -147,7 +119,8 @@ body::before {
margin: 0; margin: 0;
font-size: 2rem; font-size: 2rem;
font-weight: 700; font-weight: 700;
color: var(--pink); color: rgb(var(--accent-rgb));
transition: color 0.6s ease;
} }
.tagline { .tagline {
@ -192,28 +165,19 @@ body::before {
.link-card:hover { .link-card:hover {
transform: translateY(-3px); transform: translateY(-3px);
background: var(--surface-1); background: var(--surface-1);
border-color: var(--pink); border-color: rgb(var(--accent-rgb));
box-shadow: 0 6px 20px rgba(245, 194, 231, 0.22); box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.22);
} }
.icon { .icon {
width: 30px; width: 30px;
height: 30px; height: 30px;
flex-shrink: 0; flex-shrink: 0;
filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%); filter: brightness(0) invert(1);
transition: filter 0.15s ease; transition: filter 0.15s ease;
} }
.link-card:hover .icon { .link-card:hover .icon {
filter: invert(78%) sepia(36%) saturate(640%) hue-rotate(280deg) brightness(105%);
}
/* git.gay: white by default, true pride colors on hover */
.icon.raw {
filter: brightness(0) invert(1);
}
.link-card:hover .icon.raw {
filter: none; filter: none;
} }
@ -230,7 +194,7 @@ body::before {
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
border-radius: 10px; border-radius: 10px;
background: var(--crust); background: var(--crust);
border: 1px solid var(--pink); border: 1px solid rgb(var(--accent-rgb));
box-shadow: 0 6px 18px rgba(17, 17, 27, 0.55); box-shadow: 0 6px 18px rgba(17, 17, 27, 0.55);
white-space: nowrap; white-space: nowrap;
line-height: 1.3; line-height: 1.3;
@ -248,7 +212,7 @@ body::before {
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
border: 6px solid transparent; border: 6px solid transparent;
border-top-color: var(--pink); border-top-color: rgb(var(--accent-rgb));
} }
.link-card:hover .link-text, .link-card:hover .link-text,
@ -268,12 +232,11 @@ body::before {
color: var(--subtext-0); color: var(--subtext-0);
} }
.link-card.arch .link-title { /* "Now playing" widget, pinned top-left.
color: var(--pink); Discord presence + Spotify via Lanyard. The album-art accent colour is
} exposed as --np-accent (r, g, b) and used while .has-accent is set. */
/* "Now playing" widget, pinned top-left */
.now-playing { .now-playing {
--np-accent: 245, 194, 231; /* fallback ~ Catppuccin pink */
position: fixed; position: fixed;
top: 1rem; top: 1rem;
left: 1rem; left: 1rem;
@ -281,14 +244,15 @@ body::before {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.55rem; gap: 0.55rem;
max-width: 240px; max-width: 260px;
padding: 0.4rem 0.7rem 0.4rem 0.4rem; padding: 0.4rem 0.7rem 0.4rem 0.4rem;
border-radius: 999px; border-radius: 999px;
background: var(--surface-0); background: var(--surface-0);
border: 1px solid var(--surface-1); border: 1px solid var(--surface-1);
color: var(--text); color: var(--text);
text-decoration: none; text-decoration: none;
transition: transform 0.15s ease, border-color 0.15s ease; transition: transform 0.15s ease, border-color 0.2s ease,
border-radius 0.25s ease, box-shadow 0.2s ease;
} }
.now-playing[hidden] { .now-playing[hidden] {
@ -300,12 +264,65 @@ body::before {
border-color: var(--pink); border-color: var(--pink);
} }
/* When a track is playing the pill grows a little and squares off slightly to
make room for the progress bar, and picks up a faint album-art glow. */
.now-playing.is-live {
align-items: stretch;
border-radius: 16px;
}
.now-playing.is-live.has-accent {
border-color: rgba(var(--np-accent), 0.55);
box-shadow: 0 6px 22px -10px rgba(var(--np-accent), 0.6);
}
.now-playing.is-live:hover.has-accent {
border-color: rgba(var(--np-accent), 0.85);
}
/* Discord status dot */
/* Head row: status dot + status word, always visible (so the Discord status
shows even while a track is playing, like Mufaro's). */
.np-head {
display: flex;
align-items: center;
gap: 0.35rem;
}
.np-status {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
background: var(--overlay-0);
}
.now-playing[data-status="online"] .np-status { background: var(--green); }
.now-playing[data-status="idle"] .np-status { background: var(--yellow); }
.now-playing[data-status="dnd"] .np-status { background: var(--red); }
.now-playing[data-status="offline"] .np-status { background: var(--overlay-0); }
.np-status-label {
font-size: 0.6rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--subtext-0);
white-space: nowrap;
}
.np-art { .np-art {
width: 34px; width: 34px;
height: 34px; height: 34px;
border-radius: 50%; border-radius: 50%;
object-fit: cover; object-fit: cover;
flex-shrink: 0; flex-shrink: 0;
align-self: center;
display: none;
}
.now-playing.is-live .np-art {
display: block;
border-radius: 8px;
} }
/* Equalizer bars (only animate while live) */ /* Equalizer bars (only animate while live) */
@ -330,6 +347,10 @@ body::before {
animation: np-eq 0.9s ease-in-out infinite; animation: np-eq 0.9s ease-in-out infinite;
} }
.now-playing.has-accent .np-bars i {
background: rgb(var(--np-accent));
}
.np-bars i:nth-child(2) { .np-bars i:nth-child(2) {
animation-delay: 0.15s; animation-delay: 0.15s;
} }
@ -368,13 +389,26 @@ body::before {
line-height: 1.25; line-height: 1.25;
} }
/* "Now playing" tag only while a track is live, pushed to the right of the
status word so the head reads: [] DO NOT DISTURB ......... NOW PLAYING */
.np-label { .np-label {
display: none;
font-size: 0.6rem; font-size: 0.6rem;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.05em;
color: var(--pink); color: var(--pink);
} }
.now-playing.is-live .np-label {
display: inline;
margin-left: auto;
padding-left: 0.5rem;
}
.now-playing.is-live.has-accent .np-label {
color: rgb(var(--np-accent));
}
.np-track { .np-track {
font-size: 0.8rem; font-size: 0.8rem;
font-weight: 500; font-weight: 500;
@ -383,6 +417,10 @@ body::before {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.np-track:empty {
display: none;
}
.np-artist { .np-artist {
font-size: 0.72rem; font-size: 0.72rem;
color: var(--subtext-0); color: var(--subtext-0);
@ -391,6 +429,52 @@ body::before {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.np-artist:empty {
display: none;
}
/* Spotify progress bar — only shown while a track has timestamps */
.np-progress {
display: none;
flex-direction: column;
gap: 3px;
margin-top: 4px;
}
.now-playing.is-live.has-progress .np-progress {
display: flex;
}
.np-bar {
height: 3px;
width: 100%;
border-radius: 999px;
background: var(--surface-2);
overflow: hidden;
}
.np-fill {
display: block;
height: 100%;
width: 0%;
border-radius: 999px;
background: var(--pink);
transition: width 0.3s linear;
}
.now-playing.has-accent .np-fill {
background: rgb(var(--np-accent));
box-shadow: 0 0 8px 1px rgba(var(--np-accent), 0.55);
}
.np-times {
display: flex;
justify-content: space-between;
font-size: 0.58rem;
font-variant-numeric: tabular-nums;
color: var(--subtext-0);
}
/* Page nav, pinned bottom-left, selected item with a pointer triangle */ /* Page nav, pinned bottom-left, selected item with a pointer triangle */
.nav { .nav {
position: fixed; position: fixed;
@ -422,14 +506,14 @@ body::before {
} }
.nav-link:hover { .nav-link:hover {
border-color: var(--pink); border-color: rgb(var(--accent-rgb));
color: var(--text); color: var(--text);
transform: translateX(2px); transform: translateX(2px);
} }
.nav-link.selected { .nav-link.selected {
background: var(--pink); background: rgb(var(--accent-rgb));
border-color: var(--pink); border-color: rgb(var(--accent-rgb));
color: var(--crust); color: var(--crust);
font-weight: 700; font-weight: 700;
margin-left: 14px; margin-left: 14px;
@ -454,7 +538,7 @@ body::before {
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
border: 6px solid transparent; border: 6px solid transparent;
border-left-color: var(--pink); border-left-color: rgb(var(--accent-rgb));
} }
/* Cosmetic system badges, pinned bottom-right */ /* Cosmetic system badges, pinned bottom-right */
@ -477,10 +561,16 @@ body::before {
padding: 0.3rem 0.6rem; padding: 0.3rem 0.6rem;
border-radius: 999px; border-radius: 999px;
background: var(--surface-0); background: var(--surface-0);
border: 1px solid var(--surface-1); border: 1px solid rgba(var(--accent-rgb), 0.45);
color: var(--subtext-1); color: var(--subtext-1);
font-size: 0.75rem; font-size: 0.75rem;
white-space: nowrap; white-space: nowrap;
transition: border-color 0.6s ease, box-shadow 0.6s ease;
}
.badge:hover {
border-color: rgb(var(--accent-rgb));
box-shadow: 0 4px 14px -6px rgba(var(--accent-rgb), 0.5);
} }
.badge-icon { .badge-icon {
@ -549,17 +639,72 @@ body:has(.tech-stack) .hub {
padding-bottom: 4.5rem; padding-bottom: 4.5rem;
} }
.tech-badge { /* Simple Icons rendered via CSS mask so colour is theme-driven.
height: 28px; Markup: <span class="tech-icon pink" style="--si:url('https://cdn.simpleicons.org/SLUG')"></span> */
border-radius: 5px; .tech-icon {
transition: transform 0.15s ease, box-shadow 0.15s ease; position: relative;
width: 30px;
height: 30px;
display: inline-block;
transition: transform 0.15s ease, filter 0.15s ease;
} }
.tech-badge:hover { /* The actual icon shape — masked here so the label (::after) stays visible */
transform: translateY(-2px) scale(1.04); .tech-icon::before {
box-shadow: 0 4px 12px rgba(245, 194, 231, 0.25); content: "";
position: absolute;
inset: 0;
background-color: currentColor;
-webkit-mask: var(--si) center / contain no-repeat;
mask: var(--si) center / contain no-repeat;
} }
.tech-icon:hover {
transform: translateY(-2px) scale(1.12);
filter: drop-shadow(0 4px 8px currentColor);
}
/* Hover label — pulls text from aria-label, tinted to match the icon */
.tech-icon::after {
content: attr(aria-label);
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%) translateY(4px);
padding: 0.25rem 0.5rem;
border-radius: 6px;
background: var(--crust);
border: 1px solid currentColor;
color: var(--text);
font-size: 0.72rem;
line-height: 1;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s ease, transform 0.15s ease;
z-index: 10;
}
.tech-icon:hover::after {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
/* Catppuccin accent classes — pull from the active flavour's vars */
.tech-icon.rosewater { color: var(--rosewater); }
.tech-icon.pink { color: var(--pink); }
.tech-icon.mauve { color: var(--mauve); }
.tech-icon.red { color: var(--red); }
.tech-icon.maroon { color: var(--maroon); }
.tech-icon.peach { color: var(--peach); }
.tech-icon.yellow { color: var(--yellow); }
.tech-icon.green { color: var(--green); }
.tech-icon.teal { color: var(--teal); }
.tech-icon.sky { color: var(--sky); }
.tech-icon.sapphire { color: var(--saphire); }
.tech-icon.blue { color: var(--blue); }
.tech-icon.lavender { color: var(--lavender); }
/* ===== Secret Cat Modes toast ===== */ /* ===== Secret Cat Modes toast ===== */
.cat-toast { .cat-toast {
position: fixed; position: fixed;
@ -584,28 +729,6 @@ body:has(.tech-stack) .hub {
transform: translateX(-50%) translateY(0); transform: translateX(-50%) translateY(0);
} }
/* ===== Version tag (top-right) ===== */
.version-tag {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 6;
padding: 0.25rem 0.6rem;
border-radius: 999px;
background: var(--surface-0);
border: 1px solid var(--surface-1);
color: var(--subtext-0);
font-size: 0.72rem;
text-decoration: none;
cursor: pointer;
transition: color 0.15s ease, border-color 0.15s ease;
}
.version-tag:hover {
color: var(--pink);
border-color: var(--pink);
}
/* ===== Changelog page ===== */ /* ===== Changelog page ===== */
html:has(.changelog), html:has(.changelog),
body:has(.changelog) { body:has(.changelog) {
@ -795,11 +918,6 @@ body:has(.changelog) .hub {
font-weight: 500; font-weight: 500;
} }
.cat-lock {
font-size: 0.62rem;
color: var(--subtext-0);
}
.cat-hint { .cat-hint {
margin: 0.85rem 0 0; margin: 0.85rem 0 0;
font-size: 0.68rem; font-size: 0.68rem;
@ -811,4 +929,146 @@ body:has(.changelog) .hub {
.cat-grid { .cat-grid {
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
}
/* ============================================================
Theme switcher icon button, top-right corner
============================================================ */
.beta-bar {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 7;
}
.beta-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.35rem;
border-radius: 999px;
background: var(--surface-0);
border: 1px solid var(--surface-1);
cursor: pointer;
transition: border-color 0.15s ease, transform 0.15s ease;
}
.beta-btn:hover {
border-color: var(--pink);
transform: translateY(2px);
}
.beta-icon {
width: 22px;
height: 22px;
display: block;
}
/* ============================================================
Mobile layout
============================================================ */
@media (max-width: 640px) {
html {
height: auto;
/* Single vertical scroll root on mobile; clip horizontal overflow
so the absolutely-positioned link tooltips can't pan the page. */
overflow-x: hidden;
overflow-y: auto;
}
body,
body:has(.tech-stack),
body:has(.changelog) {
flex-direction: column;
justify-content: flex-start;
align-items: center;
gap: 1rem;
height: auto;
min-height: 100dvh;
/* html is the scroll root on mobile; body just clips its own
horizontal overflow (the absolutely-positioned link tooltips). */
overflow-x: hidden;
overflow-y: visible;
padding: 1.25rem 1rem 2rem;
}
/* 1 — Top bar: the two single-item widgets, side by side */
.topbar {
order: 1;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 0.6rem;
width: 100%;
}
.topbar .now-playing,
.topbar .beta-bar {
position: static;
inset: auto;
}
.now-playing {
max-width: 100%;
}
/* 2 — Main content */
.hub,
body:has(.tech-stack) .hub,
body:has(.changelog) .hub {
order: 2;
width: 100%;
max-width: 100%;
}
/* 3 — Page nav as a centered group */
.nav {
order: 3;
position: static;
inset: auto;
width: 100%;
}
.nav-links {
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
gap: 0.5rem;
}
/* The selected-item pointer triangle / offset only makes sense in
the vertical desktop nav drop it on mobile */
.nav-link.selected {
margin-left: 0;
}
.nav-link.selected::before {
display: none;
}
/* 4 — System badges, centered and wrapping */
.badges {
order: 4;
position: static;
inset: auto;
width: 100%;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.hub-header {
margin-bottom: 1.5rem;
}
/* Keep the tech-stack / changelog content from butting up against
the nav below it */
.tech-stack,
.changelog {
padding-bottom: 0;
}
} }

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-amd" viewBox="0 0 16 16">
<path d="m.334 0 4.358 4.359h7.15v7.15l4.358 4.358V0zM.2 9.72l4.487-4.488v6.281h6.28L6.48 16H.2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 230 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-apple" viewBox="0 0 16 16">
<path d="M11.182.008C11.148-.03 9.923.023 8.857 1.18c-1.066 1.156-.902 2.482-.878 2.516s1.52.087 2.475-1.258.762-2.391.728-2.43m3.314 11.733c-.048-.096-2.325-1.234-2.113-3.422s1.675-2.789 1.698-2.854-.597-.79-1.254-1.157a3.7 3.7 0 0 0-1.563-.434c-.108-.003-.483-.095-1.254.116-.508.139-1.653.589-1.968.607-.316.018-1.256-.522-2.267-.665-.647-.125-1.333.131-1.824.328-.49.196-1.422.754-2.074 2.237-.652 1.482-.311 3.83-.067 4.56s.625 1.924 1.273 2.796c.576.984 1.34 1.667 1.659 1.899s1.219.386 1.843.067c.502-.308 1.408-.485 1.766-.472.357.013 1.061.154 1.782.539.571.197 1.111.115 1.652-.105.541-.221 1.324-1.059 2.238-2.758q.52-1.185.473-1.282"/>
<path d="M11.182.008C11.148-.03 9.923.023 8.857 1.18c-1.066 1.156-.902 2.482-.878 2.516s1.52.087 2.475-1.258.762-2.391.728-2.43m3.314 11.733c-.048-.096-2.325-1.234-2.113-3.422s1.675-2.789 1.698-2.854-.597-.79-1.254-1.157a3.7 3.7 0 0 0-1.563-.434c-.108-.003-.483-.095-1.254.116-.508.139-1.653.589-1.968.607-.316.018-1.256-.522-2.267-.665-.647-.125-1.333.131-1.824.328-.49.196-1.422.754-2.074 2.237-.652 1.482-.311 3.83-.067 4.56s.625 1.924 1.273 2.796c.576.984 1.34 1.667 1.659 1.899s1.219.386 1.843.067c.502-.308 1.408-.485 1.766-.472.357.013 1.061.154 1.782.539.571.197 1.111.115 1.652-.105.541-.221 1.324-1.059 2.238-2.758q.52-1.185.473-1.282"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640">
<path d="M320.7 56.2C296.6 115.2 282.1 153.9 255.3 211.2C271.7 228.6 291.9 248.8 324.7 271.7C289.5 257.2 265.5 242.8 247.5 227.7C213.2 299.3 159.4 401.2 50.3 597.1C136 547.6 202.5 517.1 264.4 505.5C261.7 494.1 260.3 481.7 260.4 468.8L260.5 466.1C261.9 411.2 290.4 368.9 324.3 371.7C358.2 374.5 384.5 421.5 383.1 476.4C382.8 486.7 381.7 496.6 379.7 505.8C440.9 517.8 506.7 548.2 591.3 597C574.6 566.3 559.7 538.7 545.5 512.3C523.1 494.9 499.8 472.4 452.2 447.9C484.9 456.4 508.5 466.2 526.7 477.2C382.2 208.1 370.5 172.4 320.9 56.1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 995 KiB

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bluesky" viewBox="0 0 16 16">
<path d="M3.468 1.948C5.303 3.325 7.276 6.118 8 7.616c.725-1.498 2.698-4.29 4.532-5.668C13.855.955 16 .186 16 2.632c0 .489-.28 4.105-.444 4.692-.572 2.04-2.653 2.561-4.504 2.246 3.236.551 4.06 2.375 2.281 4.2-3.376 3.464-4.852-.87-5.23-1.98-.07-.204-.103-.3-.103-.218 0-.081-.033.014-.102.218-.379 1.11-1.855 5.444-5.231 1.98-1.778-1.825-.955-3.65 2.28-4.2-1.85.315-3.932-.205-4.503-2.246C.28 6.737 0 3.12 0 2.632 0 .186 2.145.955 3.468 1.948"/>
</svg>

Before

Width:  |  Height:  |  Size: 580 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-discord" viewBox="0 0 16 16">
<path d="M13.545 2.907a13.2 13.2 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.2 12.2 0 0 0-3.658 0 8 8 0 0 0-.412-.833.05.05 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.04.04 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032q.003.022.021.037a13.3 13.3 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019q.463-.63.818-1.329a.05.05 0 0 0-.01-.059l-.018-.011a9 9 0 0 1-1.248-.595.05.05 0 0 1-.02-.066l.015-.019q.127-.095.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.05.05 0 0 1 .053.007q.121.1.248.195a.05.05 0 0 1-.004.085 8 8 0 0 1-1.249.594.05.05 0 0 0-.03.03.05.05 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.2 13.2 0 0 0 4.001-2.02.05.05 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.03.03 0 0 0-.02-.019m-8.198 7.307c-.789 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612m5.316 0c-.788 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-fill" viewBox="0 0 16 16">
<path d="M.05 3.555A2 2 0 0 1 2 2h12a2 2 0 0 1 1.95 1.555L8 8.414zM0 4.697v7.104l5.803-3.558zM6.761 8.83l-6.57 4.027A2 2 0 0 0 2 14h12a2 2 0 0 0 1.808-1.144l-6.57-4.027L8 9.586zm3.436-.586L16 11.801V4.697z"/>
</svg>

Before

Width:  |  Height:  |  Size: 349 B

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 556.37 303.36" style="enable-background:new 0 0 556.37 303.36;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;}
</style>
<g>
<polygon points="32.85,271.82 17.96,271.82 17.96,260.06 14.17,260.06 14.17,288.69 17.96,288.69 17.96,275.2 32.85,275.2
32.85,288.69 36.63,288.69 36.63,260.06 32.85,260.06 "/>
<path d="M62.65,261.45c-2.12-1.26-4.51-1.89-7.15-1.89c-4.04,0-7.33,1.34-9.88,4.04c-2.55,2.69-3.83,6.41-3.83,11.16
c0,2.52,0.55,4.9,1.64,7.15c1.09,2.25,2.7,4.03,4.82,5.33c2.12,1.3,4.53,1.95,7.23,1.95c2.49,0,4.8-0.59,6.95-1.77
c2.15-1.18,3.81-2.91,4.98-5.21c1.17-2.29,1.76-4.89,1.76-7.79c0-2.86-0.56-5.43-1.67-7.68C66.39,264.47,64.77,262.71,62.65,261.45
z M62.5,282.93c-1.84,2.01-4.19,3.01-7.04,3.01c-2.8,0-5.13-0.99-6.98-2.98c-1.86-1.99-2.78-4.7-2.78-8.16
c0-4.31,0.97-7.39,2.9-9.23c1.93-1.84,4.24-2.77,6.92-2.77c1.89,0,3.59,0.48,5.11,1.44s2.67,2.3,3.46,4.04
c0.79,1.74,1.18,3.77,1.18,6.1C65.27,278.08,64.35,280.93,62.5,282.93z"/>
<polygon points="262.41,214.22 247.52,214.22 247.52,202.46 243.73,202.46 243.73,231.1 247.52,231.1 247.52,217.6 262.41,217.6
262.41,231.1 266.2,231.1 266.2,202.46 262.41,202.46 "/>
<polygon points="312.29,127.82 297.4,127.82 297.4,116.06 293.62,116.06 293.62,144.7 297.4,144.7 297.4,131.2 312.29,131.2
312.29,144.7 316.08,144.7 316.08,116.06 312.29,116.06 "/>
<rect x="173.77" y="159.62" transform="matrix(0.4998 -0.8661 0.8661 0.4998 -70.4902 242.7992)" width="2.4" height="45.62"/>
<rect x="114.5" y="193.83" width="2.4" height="45.64"/>
<rect x="152.16" y="249.67" transform="matrix(0.8662 -0.4997 0.4997 0.8662 -101.9474 120.9965)" width="45.62" height="2.4"/>
<polygon points="260.54,193.57 249.4,193.57 248.97,195.97 260.97,195.97 "/>
<polygon points="258.36,181.33 251.59,181.33 251.16,183.73 258.79,183.73 "/>
<polygon points="256.17,169.09 253.77,169.09 253.35,171.49 256.6,171.49 "/>
<path d="M420.15,41.85c2.12,1.3,4.53,1.95,7.23,1.95c2.49,0,4.8-0.59,6.95-1.77s3.81-2.91,4.98-5.21s1.76-4.89,1.76-7.79
c0-2.87-0.56-5.43-1.67-7.69s-2.73-4.02-4.85-5.28c-2.12-1.26-4.51-1.89-7.15-1.89c-4.04,0-7.33,1.34-9.88,4.03
c-2.55,2.69-3.83,6.41-3.83,11.16c0,2.51,0.55,4.9,1.64,7.15S418.03,40.55,420.15,41.85z M420.5,20.2
c1.93-1.84,4.24-2.76,6.92-2.76c1.89,0,3.59,0.48,5.11,1.44s2.67,2.3,3.46,4.04s1.18,3.77,1.18,6.1c0,3.69-0.92,6.53-2.77,8.54
s-4.19,3.01-7.04,3.01c-2.8,0-5.13-0.99-6.98-2.98s-2.78-4.7-2.78-8.15C417.6,25.12,418.56,22.04,420.5,20.2z"/>
<polygon points="464.75,26.44 449.87,26.44 449.87,14.68 446.08,14.68 446.08,43.31 449.87,43.31 449.87,29.82 464.75,29.82
464.75,43.31 468.54,43.31 468.54,14.68 464.75,14.68 "/>
<path d="M426.42,51.04l-11.41-3.71l-6.53,35.4l-52.4,17.03l4.66-55.9h-12l4.62,55.42l-48.5-28l-51.08,29.49v57.59l-48.68,28.12
l-49.88-28.8l-51.08,29.48v57.6l-31.34,18.1l1.2,2.06l31.35-18.08l49.88,28.8l49.88-28.8l49.88,28.8l51.08-29.48v-57.6l48.82-28.2
l55.1,17.92l34.88-48.02L410.9,83.51L426.42,51.04z M155.21,272.87l-48.68-28.12v-56.2l48.68-28.12l48.68,28.12v56.2L155.21,272.87
z M254.97,272.87l-48.68-28.12v-56.2l48.68-28.12l48.68,28.12v56.2L254.97,272.87z M306.35,185.61l4.51-34.64h-12l4.51,34.64
l-47.19-27.26v-56.21l48.68-28.11l48.68,28.11v56.21L306.35,185.61z M441.89,130.25l-32.83,45.18l-53.12-17.26v-55.85l53.12-17.26
L441.89,130.25z"/>
<polygon points="362.17,214.22 347.28,214.22 347.28,202.46 343.49,202.46 343.49,231.1 347.28,231.1 347.28,217.6 362.17,217.6
362.17,231.1 365.96,231.1 365.96,202.46 362.17,202.46 "/>
<polygon points="348.73,195.97 360.73,195.97 360.31,193.57 349.16,193.57 "/>
<polygon points="350.92,183.73 358.55,183.73 358.12,181.33 351.35,181.33 "/>
<polygon points="353.53,169.09 353.11,171.49 356.36,171.49 355.93,169.09 "/>
<path d="M508.21,117.45c-2.12-1.26-4.51-1.89-7.15-1.89c-4.04,0-7.33,1.34-9.88,4.03c-2.55,2.69-3.83,6.41-3.83,11.16
c0,2.51,0.55,4.9,1.64,7.15s2.7,4.03,4.82,5.33c2.12,1.3,4.53,1.95,7.23,1.95c2.49,0,4.8-0.59,6.95-1.77s3.81-2.91,4.98-5.21
c1.17-2.29,1.76-4.89,1.76-7.79c0-2.87-0.56-5.43-1.67-7.69C511.95,120.47,510.33,118.71,508.21,117.45z M508.06,138.93
c-1.84,2.01-4.19,3.01-7.04,3.01c-2.8,0-5.13-0.99-6.98-2.98s-2.78-4.7-2.78-8.15c0-4.31,0.96-7.39,2.9-9.23s4.24-2.76,6.92-2.76
c1.89,0,3.59,0.48,5.11,1.44s2.67,2.3,3.46,4.04s1.18,3.77,1.18,6.1C510.83,134.08,509.9,136.93,508.06,138.93z"/>
<polygon points="538.4,116.06 538.4,127.82 523.52,127.82 523.52,116.06 519.73,116.06 519.73,144.7 523.52,144.7 523.52,131.2
538.4,131.2 538.4,144.7 542.19,144.7 542.19,116.06 "/>
<polygon points="478.41,135.83 480.81,136.25 480.81,124.25 478.41,124.67 "/>
<polygon points="465.9,133.63 468.3,134.05 468.3,126.45 465.9,126.85 "/>
<polygon points="453.38,131.45 455.78,131.87 455.78,128.63 453.38,129.05 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 120 120" width="32" height="32"><defs><clipPath id="a" clipPathUnits="userSpaceOnUse"><path stroke-width="1.306" d="m117.728 54.656-52.39-52.39a7.727 7.727 0 0 0-10.931 0l-10.875 10.88 13.797 13.8a9.18 9.18 0 0 1 11.622 11.702l13.3 13.3a9.18 9.18 0 0 1 9.505 2.183 9.194 9.194 0 0 1 0 13.003 9.205 9.205 0 0 1-13.013 0 9.2 9.2 0 0 1-1.995-10.003L64.343 44.728v32.645c5.642 2.788 6.879 10.294 2.428 14.744a9.19 9.19 0 0 1-13.002 0 9.194 9.194 0 0 1 0-13.005 9.2 9.2 0 0 1 3.009-2.01V44.158a9.206 9.206 0 0 1-4.988-12.06L38.186 18.493 2.26 54.41a7.74 7.74 0 0 0 0 10.931l52.392 52.399a7.736 7.736 0 0 0 10.93 0l52.157-52.152a7.74 7.74 0 0 0 0-10.932"/></clipPath></defs><g clip-path="url(#a)" paint-order="markers stroke fill"><rect width="120" height="22.5" fill="#fe9494" ry="0"/><rect width="120" height="22.5" y="20" fill="#ffc783" ry="0"/><rect width="120" height="22.5" y="40" fill="#fff683" ry="0"/><rect width="120" height="22.5" y="60.001" fill="#69cb86" ry="0"/><rect width="120" height="22.5" y="80.001" fill="#83a8ff" ry="0"/><rect width="120" height="19.999" y="100.002" fill="#c56ad4" ry="0"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>

Before

Width:  |  Height:  |  Size: 708 B

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-linkedin" viewBox="0 0 16 16">
<path d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854zm4.943 12.248V6.169H2.542v7.225zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248S2.4 3.226 2.4 3.934c0 .694.521 1.248 1.327 1.248zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016l.016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225z"/>
</svg>

Before

Width:  |  Height:  |  Size: 666 B

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-mastodon" viewBox="0 0 16 16">
<path d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a4 4 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522q0-1.288.66-2.046c.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764q.662.757.661 2.046z"/>
</svg>

Before

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reddit" viewBox="0 0 16 16">
<path d="M6.167 8a.83.83 0 0 0-.83.83c0 .459.372.84.83.831a.831.831 0 0 0 0-1.661m1.843 3.647c.315 0 1.403-.038 1.976-.611a.23.23 0 0 0 0-.306.213.213 0 0 0-.306 0c-.353.363-1.126.487-1.67.487-.545 0-1.308-.124-1.671-.487a.213.213 0 0 0-.306 0 .213.213 0 0 0 0 .306c.564.563 1.652.61 1.977.61zm.992-2.807c0 .458.373.83.831.83s.83-.381.83-.83a.831.831 0 0 0-1.66 0z"/>
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.828-1.165c-.315 0-.602.124-.812.325-.801-.573-1.9-.945-3.121-.993l.534-2.501 1.738.372a.83.83 0 1 0 .83-.869.83.83 0 0 0-.744.468l-1.938-.41a.2.2 0 0 0-.153.028.2.2 0 0 0-.086.134l-.592 2.788c-1.24.038-2.358.41-3.17.992-.21-.2-.496-.324-.81-.324a1.163 1.163 0 0 0-.478 2.224q-.03.17-.029.353c0 1.795 2.091 3.256 4.669 3.256s4.668-1.451 4.668-3.256c0-.114-.01-.238-.029-.353.401-.181.688-.592.688-1.069 0-.65-.525-1.165-1.165-1.165"/>
</svg>

Before

Width:  |  Height:  |  Size: 984 B

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-globe2" viewBox="0 0 16 16">
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m7.5-6.923c-.67.204-1.335.82-1.887 1.855q-.215.403-.395.872c.705.157 1.472.257 2.282.287zM4.249 3.539q.214-.577.481-1.078a7 7 0 0 1 .597-.933A7 7 0 0 0 3.051 3.05q.544.277 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9 9 0 0 1-1.565-.667A6.96 6.96 0 0 0 1.018 7.5zm1.4-2.741a12.3 12.3 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332M8.5 5.09V7.5h2.99a12.3 12.3 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.035.987.176 1.914.399 2.741A13.6 13.6 0 0 1 7.5 10.91V8.5zm3.99 0v2.409c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741zm-3.282 3.696q.18.469.395.872c.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.282.287zm.11 2.276a7 7 0 0 1-.598-.933 9 9 0 0 1-.481-1.079 8.4 8.4 0 0 0-1.198.49 7 7 0 0 0 2.276 1.522zm-1.383-2.964A13.4 13.4 0 0 1 3.508 8.5h-2.49a6.96 6.96 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667m6.728 2.964a7 7 0 0 0 2.275-1.521 8.4 8.4 0 0 0-1.197-.49 9 9 0 0 1-.481 1.078 7 7 0 0 1-.597.933M8.5 11.909v3.014c.67-.204 1.335-.82 1.887-1.855q.216-.403.395-.872A12.6 12.6 0 0 0 8.5 11.91zm3.555-.401c.57.185 1.095.409 1.565.667A6.96 6.96 0 0 0 14.982 8.5h-2.49a13.4 13.4 0 0 1-.437 3.008M14.982 7.5a6.96 6.96 0 0 0-1.362-3.675c-.47.258-.995.482-1.565.667.248.92.4 1.938.437 3.008zM11.27 2.461q.266.502.482 1.078a8.4 8.4 0 0 0 1.196-.49 7 7 0 0 0-2.275-1.52c.218.283.418.597.597.932m-.488 1.343a8 8 0 0 0-.395-.872C9.835 1.897 9.17 1.282 8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-spotify" viewBox="0 0 16 16">
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0m3.669 11.538a.5.5 0 0 1-.686.165c-1.879-1.147-4.243-1.407-7.028-.77a.499.499 0 0 1-.222-.973c3.048-.696 5.662-.397 7.77.892a.5.5 0 0 1 .166.686m.979-2.178a.624.624 0 0 1-.858.205c-2.15-1.321-5.428-1.704-7.972-.932a.625.625 0 0 1-.362-1.194c2.905-.881 6.517-.454 8.986 1.063a.624.624 0 0 1 .206.858m.084-2.268C10.154 5.56 5.9 5.419 3.438 6.166a.748.748 0 1 1-.434-1.432c2.825-.857 7.523-.692 10.492 1.07a.747.747 0 1 1-.764 1.288"/>
</svg>

Before

Width:  |  Height:  |  Size: 609 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitch" viewBox="0 0 16 16">
<path d="M3.857 0 1 2.857v10.286h3.429V16l2.857-2.857H9.57L14.714 8V0zm9.714 7.429-2.285 2.285H9l-2 2v-2H4.429V1.143h9.142z"/>
<path d="M11.857 3.143h-1.143V6.57h1.143zm-3.143 0H7.571V6.57h1.143z"/>
</svg>

Before

Width:  |  Height:  |  Size: 334 B

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitter" viewBox="0 0 16 16">
<path d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334q.002-.211-.006-.422A6.7 6.7 0 0 0 16 3.542a6.7 6.7 0 0 1-1.889.518 3.3 3.3 0 0 0 1.447-1.817 6.5 6.5 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.32 9.32 0 0 1-6.767-3.429 3.29 3.29 0 0 0 1.018 4.382A3.3 3.3 0 0 1 .64 6.575v.045a3.29 3.29 0 0 0 2.632 3.218 3.2 3.2 0 0 1-.865.115 3 3 0 0 1-.614-.057 3.28 3.28 0 0 0 3.067 2.277A6.6 6.6 0 0 1 .78 13.58a6 6 0 0 1-.78-.045A9.34 9.34 0 0 0 5.026 15"/>
</svg>

Before

Width:  |  Height:  |  Size: 586 B

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16">
<path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.01 2.01 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.01 2.01 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31 31 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.01 2.01 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A100 100 0 0 1 7.858 2zM6.4 5.209v4.818l4.157-2.408z"/>
</svg>

Before

Width:  |  Height:  |  Size: 893 B

View File

@ -1,13 +1,17 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<!-- Ari was here :3 -->
<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">
<title>Clove Twilight - Link Center</title> <title>Clove Twilight - Link Center</title>
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg"> <link rel="stylesheet" href="/css/themes/mocha.css">
<link rel="stylesheet" href="/css/themes/macchiato.css">
<link rel="stylesheet" href="/css/themes/frappe.css">
<link rel="stylesheet" href="/css/themes/latte.css">
<script>try { var f = localStorage.getItem('ctpFlavor'); document.documentElement.setAttribute('data-flavor', ['mocha', 'macchiato', 'frappe', 'latte'].indexOf(f) >= 0 ? f : 'mocha'); } catch (e) { document.documentElement.setAttribute('data-flavor', 'mocha'); }</script>
<link rel="icon" type="image/svg+xml" href="/images/favicon/favicon.svg">
<!-- SEO Meta Tags --> <!-- SEO Meta Tags -->
<meta name="description" content="Link Center for Clove Twilight" /> <meta name="description" content="Link Center for Clove Twilight" />
@ -25,7 +29,7 @@
<meta name="theme-color" content="#f5c2e7" /> <meta name="theme-color" content="#f5c2e7" />
<!-- Open Graph / Discord / Facebook --> <!-- Open Graph / Discord / Facebook -->
<meta property="og:image" content="https://clove.is-a.dev/images/favicon.png" /> <meta property="og:image" content="https://clove.is-a.dev/images/favicon/favicon.png" />
<meta property="og:site_name" content="clove.is-a.dev" /> <meta property="og:site_name" content="clove.is-a.dev" />
<meta property="og:title" content="Clove Twilight | Links" /> <meta property="og:title" content="Clove Twilight | Links" />
<meta property="og:description" content="Link Center for Clove Twilight" /> <meta property="og:description" content="Link Center for Clove Twilight" />
@ -34,7 +38,7 @@
<meta property="og:locale" content="en_GB" /> <meta property="og:locale" content="en_GB" />
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:image" content="https://clove.is-a.dev/images/favicon.png" /> <meta name="twitter:image" content="https://clove.is-a.dev/images/favicon/favicon.png" />
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Clove Twilight | Links" /> <meta name="twitter:title" content="Clove Twilight | Links" />
<meta name="twitter:description" content="Link Center for Clove Twilight" /> <meta name="twitter:description" content="Link Center for Clove Twilight" />
@ -45,26 +49,32 @@
<nav class="nav-links"> <nav class="nav-links">
<a class="nav-link selected" data-href="/">Link Center</a> <a class="nav-link selected" data-href="/">Link Center</a>
<a class="nav-link" data-href="/tech-stack">Tech Stack</a> <a class="nav-link" data-href="/tech-stack">Tech Stack</a>
<a class="nav-link is-a-dev" data-href="https://doughmination.is-a.dev" target="_blank" rel="noopener">Beta Site</a> <a class="nav-link is-a-dev" data-href="https://clove.is-a.dev" target="_blank"
rel="noopener noreferrer">clove.is-a.dev</a>
</nav> </nav>
</header> </header>
<a rel="me" href="https://mastodon.social/@doughmination" style="display: none;"></a>
<a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden> <a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden>
<img class="np-art" alt="" referrerpolicy="no-referrer"> <img class="np-art" alt="" referrerpolicy="no-referrer" crossorigin="anonymous">
<span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span> <span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
<span class="np-text"> <span class="np-text">
<span class="np-label">Now playing</span> <span class="np-head">
<span class="np-status" aria-hidden="true"></span>
<span class="np-status-label"></span>
<span class="np-label">Now playing</span>
</span>
<span class="np-track"></span> <span class="np-track"></span>
<span class="np-artist"></span> <span class="np-artist"></span>
<span class="np-progress" aria-hidden="true">
<span class="np-bar"><span class="np-fill"></span></span>
<span class="np-times"><span class="np-cur">0:00</span><span class="np-dur">0:00</span></span>
</span>
</span> </span>
</a> </a>
<a class="version-tag" data-href="/changelog" title="Changelog">v1.4.0</a>
<main class="hub"> <main class="hub">
<header class="hub-header"> <header class="hub-header">
<img class="pfp" src="/images/avatar.png" alt="Clove Twilight avatar"> <img class="pfp" src="/images/favicon/avatar.png" alt="Clove Twilight avatar">
<h1>Clove Twilight</h1> <h1>Clove Twilight</h1>
<h2 class="pronouns">(fae/faer)</h2> <h2 class="pronouns">(fae/faer)</h2>
<p class="tagline">Link Center</p> <p class="tagline">Link Center</p>
@ -72,7 +82,7 @@
<nav class="links"> <nav class="links">
<a class="link-card" href="https://github.com/doughmination"> <a class="link-card" href="https://github.com/doughmination">
<img class="icon" src="/images/github.svg" alt=""> <img class="icon" src="/images/socials/github.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">GitHub</span> <span class="link-title">GitHub</span>
<span class="link-sub">@doughmination</span> <span class="link-sub">@doughmination</span>
@ -80,7 +90,7 @@
</a> </a>
<a class="link-card" href="https://git.gay/doughmination"> <a class="link-card" href="https://git.gay/doughmination">
<img class="icon raw" src="/images/git-gay.svg" alt=""> <img class="icon" src="/images/socials/git-gay.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Git.Gay</span> <span class="link-title">Git.Gay</span>
<span class="link-sub">@doughmination</span> <span class="link-sub">@doughmination</span>
@ -88,7 +98,7 @@
</a> </a>
<a class="link-card" href="https://x.com/DoughminCEO"> <a class="link-card" href="https://x.com/DoughminCEO">
<img class="icon" src="/images/twitter.svg" alt=""> <img class="icon" src="/images/socials/twitter.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Twitter</span> <span class="link-title">Twitter</span>
<span class="link-sub">@DoughminCEO</span> <span class="link-sub">@DoughminCEO</span>
@ -96,7 +106,7 @@
</a> </a>
<a class="link-card" href="https://bsky.app/profile/doughmination.win"> <a class="link-card" href="https://bsky.app/profile/doughmination.win">
<img class="icon" src="/images/bluesky.svg" alt=""> <img class="icon" src="/images/socials/bluesky.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Bluesky</span> <span class="link-title">Bluesky</span>
<span class="link-sub">@doughmination.win</span> <span class="link-sub">@doughmination.win</span>
@ -104,7 +114,7 @@
</a> </a>
<a class="link-card" href="https://www.linkedin.com/in/estrogen/"> <a class="link-card" href="https://www.linkedin.com/in/estrogen/">
<img class="icon" src="/images/linkedin.svg" alt=""> <img class="icon" src="/images/socials/linkedin.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">LinkedIn</span> <span class="link-title">LinkedIn</span>
<span class="link-sub">Clove Twilight</span> <span class="link-sub">Clove Twilight</span>
@ -112,7 +122,7 @@
</a> </a>
<a class="link-card" href="https://open.spotify.com/user/x060f5w4ftwv8zc8fi9662t70"> <a class="link-card" href="https://open.spotify.com/user/x060f5w4ftwv8zc8fi9662t70">
<img class="icon" src="/images/spotify.svg" alt=""> <img class="icon" src="/images/socials/spotify.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Spotify</span> <span class="link-title">Spotify</span>
<span class="link-sub">doughmination</span> <span class="link-sub">doughmination</span>
@ -120,7 +130,7 @@
</a> </a>
<a class="link-card" href="https://discord.gg/TransRights"> <a class="link-card" href="https://discord.gg/TransRights">
<img class="icon" src="/images/discord.svg" alt=""> <img class="icon" src="/images/socials/discord.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Discord</span> <span class="link-title">Discord</span>
<span class="link-sub">Girls Discord Server</span> <span class="link-sub">Girls Discord Server</span>
@ -128,7 +138,7 @@
</a> </a>
<a class="link-card" href="https://www.twitch.tv/doughminationgaming"> <a class="link-card" href="https://www.twitch.tv/doughminationgaming">
<img class="icon" src="/images/twitch.svg" alt=""> <img class="icon" src="/images/socials/twitch.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Twitch</span> <span class="link-title">Twitch</span>
<span class="link-sub">@doughminationgaming</span> <span class="link-sub">@doughminationgaming</span>
@ -136,7 +146,7 @@
</a> </a>
<a class="link-card" href="https://www.reddit.com/user/XerinDotZero/"> <a class="link-card" href="https://www.reddit.com/user/XerinDotZero/">
<img class="icon" src="/images/reddit.svg" alt=""> <img class="icon" src="/images/socials/reddit.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Reddit</span> <span class="link-title">Reddit</span>
<span class="link-sub">u/XerinDotZero</span> <span class="link-sub">u/XerinDotZero</span>
@ -144,7 +154,7 @@
</a> </a>
<a class="link-card" href="https://www.youtube.com/@CloveTwiGaming"> <a class="link-card" href="https://www.youtube.com/@CloveTwiGaming">
<img class="icon" src="/images/youtube.svg" alt=""> <img class="icon" src="/images/socials/youtube.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">YouTube</span> <span class="link-title">YouTube</span>
<span class="link-sub">@CloveTwiGaming</span> <span class="link-sub">@CloveTwiGaming</span>
@ -152,7 +162,7 @@
</a> </a>
<a class="link-card" rel="me" href="https://mastodon.social/@doughmination"> <a class="link-card" rel="me" href="https://mastodon.social/@doughmination">
<img class="icon" src="/images/mastodon.svg" alt=""> <img class="icon" src="/images/socials/mastodon.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Mastodon</span> <span class="link-title">Mastodon</span>
<span class="link-sub">@doughmination@mastodon.social</span> <span class="link-sub">@doughmination@mastodon.social</span>
@ -160,7 +170,7 @@
</a> </a>
<a class="link-card" href="mailto:admin@doughmination.win"> <a class="link-card" href="mailto:admin@doughmination.win">
<img class="icon" src="/images/email.svg" alt=""> <img class="icon" src="/images/socials/email.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">Email</span> <span class="link-title">Email</span>
<span class="link-sub">admin@doughmination.win</span> <span class="link-sub">admin@doughmination.win</span>
@ -168,7 +178,7 @@
</a> </a>
<a class="link-card" href="https://doughmination.win/"> <a class="link-card" href="https://doughmination.win/">
<img class="icon" src="/images/site.svg" alt=""> <img class="icon" src="/images/socials/site.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">My Company Website</span> <span class="link-title">My Company Website</span>
<span class="link-sub">doughmination.win</span> <span class="link-sub">doughmination.win</span>
@ -176,7 +186,7 @@
</a> </a>
<a class="link-card" href="https://doughmination.co.uk/"> <a class="link-card" href="https://doughmination.co.uk/">
<img class="icon" src="/images/site.svg" alt=""> <img class="icon" src="/images/socials/site.svg" alt="">
<span class="link-text"> <span class="link-text">
<span class="link-title">My Portfolio</span> <span class="link-title">My Portfolio</span>
<span class="link-sub">doughmination.co.uk</span> <span class="link-sub">doughmination.co.uk</span>
@ -188,27 +198,28 @@
<aside class="badges" aria-label="System badges"> <aside class="badges" aria-label="System badges">
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/amd.svg" alt=""> <img class="badge-icon" src="/images/misc/amd.svg" alt="">
AMD Purist AMD Purist
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/arch.svg" alt=""> <img class="badge-icon" src="/images/misc/arch.svg" alt="">
I use arch btw I use arch btw
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/debian.svg" alt=""> <img class="badge-icon" src="/images/misc/debian.svg" alt="">
Debian Professional Debian Professional
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/apple.svg" alt=""> <img class="badge-icon" src="/images/misc/apple.svg" alt="">
Apple Ecosystem Enthusiast Apple Ecosystem Enthusiast
</span> </span>
</aside> </aside>
<script src="/js/cat.js" data-cat="/images/oneko.gif"></script> <script src="/js/cat.js" data-cat="/images/misc/oneko.gif"></script>
<script src="/js/nav.js"></script> <script src="/js/nav.js"></script>
<script src="/js/now-playing.js"></script> <script src="/js/now-playing.js"></script>
<script src="/js/cat-modes.js"></script> <script src="/js/flavors.js"></script>
<script src="/js/site-switcher.js"></script>
</body> </body>
</html> </html>

144
js/cat.js
View File

@ -204,7 +204,7 @@
} }
idleAnimation = idleAnimation =
avalibleIdleAnimations[ avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length) Math.floor(Math.random() * avalibleIdleAnimations.length)
]; ];
} }
@ -277,3 +277,145 @@
init(); init();
})(); })();
/* ============================================================
Secret cat modes click the cat to cycle/unlock looks,
press C to open the picker. (merged from cat-modes.js)
============================================================ */
const CAT_MODES = [
{ name: "Classic", filter: "none" },
{ name: "Shadow Cat", filter: "invert(1) drop-shadow(0 0 3px #cba6f7)" },
{ name: "Ghost Cat", filter: "grayscale(1) brightness(1.7) opacity(0.55) drop-shadow(0 0 4px #89dceb)" },
{ name: "CRT Cat", filter: "invert(48%) sepia(80%) saturate(2000%) hue-rotate(85deg) brightness(0.9) contrast(1.2)" },
{ name: "Vaporwave Cat", filter: "invert(60%) sepia(90%) saturate(3000%) hue-rotate(280deg) brightness(0.95)" },
{ name: "Gold Cat", filter: "invert(75%) sepia(85%) saturate(1400%) hue-rotate(8deg) brightness(1.0)" },
{ name: "Sapphire Cat", filter: "invert(45%) sepia(90%) saturate(2500%) hue-rotate(200deg) brightness(1.0)" },
{ name: "Dusty Cat", filter: "invert(60%)" },
];
const UNLOCK_EVERY = 5; // clicks needed to unlock each new mode
const SPRITE = "/images/misc/oneko.gif";
const IDLE_POS = "-96px -96px"; // idle frame of the sprite sheet
(function catModes() {
const oneko = document.getElementById("oneko");
if (!oneko) return;
oneko.style.pointerEvents = "auto";
oneko.style.cursor = "pointer";
const ls = window.localStorage;
let clicks = parseInt(ls.getItem("onekoClicks") || "0", 10);
let mode = parseInt(ls.getItem("onekoMode") || "0", 10);
const unlockedCount = () =>
Math.min(CAT_MODES.length, 1 + Math.floor(clicks / UNLOCK_EVERY));
const isUnlocked = (i) => i < unlockedCount();
const apply = (i) => (oneko.style.filter = CAT_MODES[i].filter);
/* ---------- picker overlay (no visible trigger — press C to find it) ---------- */
const overlay = document.createElement("div");
overlay.className = "cat-picker";
overlay.hidden = true;
overlay.innerHTML = `
<div class="cat-picker-panel" role="dialog" aria-label="Choose a cat">
<div class="cat-picker-head">
<span>Cat collection</span>
<button class="cat-picker-close" type="button" aria-label="Close">&times;</button>
</div>
<div class="cat-grid"></div>
<p class="cat-hint">Some cats are still hidden&hellip; &middot; press C to toggle</p>
</div>`;
document.body.appendChild(overlay);
const grid = overlay.querySelector(".cat-grid");
function renderGrid() {
grid.innerHTML = "";
CAT_MODES.forEach((c, i) => {
const unlocked = isUnlocked(i);
const opt = document.createElement(unlocked ? "button" : "div");
opt.className =
"cat-option" + (unlocked ? "" : " locked") + (i === mode ? " current" : "");
if (unlocked) opt.type = "button";
const previewFilter = unlocked ? c.filter : "brightness(0) opacity(0.3)";
opt.innerHTML = `
<span class="cat-preview" style="background-image:url('${SPRITE}');background-position:${IDLE_POS};filter:${previewFilter}"></span>
<span class="cat-name">${unlocked ? c.name : "???"}</span>`;
if (unlocked) opt.addEventListener("click", () => selectMode(i));
grid.appendChild(opt);
});
}
function selectMode(i) {
mode = i;
ls.setItem("onekoMode", String(i));
apply(i);
renderGrid();
}
const openPicker = () => {
renderGrid();
overlay.hidden = false;
};
const closePicker = () => (overlay.hidden = true);
const togglePicker = () => (overlay.hidden ? openPicker() : closePicker());
overlay
.querySelector(".cat-picker-close")
.addEventListener("click", closePicker);
overlay.addEventListener("click", (e) => {
if (e.target === overlay) closePicker();
});
document.addEventListener("keydown", (e) => {
// ignore while typing in a field or with modifier keys held
const typing = /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement?.tagName || "");
if (e.key === "Escape" && !overlay.hidden) {
closePicker();
} else if (
(e.key === "c" || e.key === "C") &&
!e.ctrlKey && !e.metaKey && !e.altKey && !typing
) {
togglePicker();
}
});
/* ---------- toast ---------- */
let toastEl, toastTimer;
function toast(msg) {
if (!toastEl) {
toastEl = document.createElement("div");
toastEl.className = "cat-toast";
document.body.appendChild(toastEl);
}
toastEl.textContent = msg;
toastEl.classList.remove("show");
void toastEl.offsetWidth;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(() => toastEl.classList.remove("show"), 1700);
}
/* ---------- init + cat click ---------- */
mode = Math.max(0, Math.min(mode, unlockedCount() - 1));
apply(mode);
oneko.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const before = unlockedCount();
clicks += 1;
ls.setItem("onekoClicks", String(clicks));
const after = unlockedCount();
if (after > before) {
mode = after - 1;
toast(`✨ Unlocked: ${CAT_MODES[mode].name}!`);
} else {
mode = (mode + 1) % after;
toast(CAT_MODES[mode].name);
}
ls.setItem("onekoMode", String(mode));
apply(mode);
if (!overlay.hidden) renderGrid();
});
})();

View File

@ -1,65 +1,270 @@
const LASTFM_USER = "Real_AlexTLM"; /* Now Playing Discord presence + Spotify via Lanyard (lanyard.rest)
const LASTFM_API_KEY = "768e8bd0d366f4d6c7874740ca6610ad"; *
* Shows your live Discord status (online / idle / dnd / offline) and, when
* you're listening on Spotify, the track, artist, album art and a live
* progress bar. 100% client-side works fine on GitHub Pages.
*
* Setup:
* 1. Join the Lanyard Discord server: https://discord.gg/lanyard
* (their bot has to share a server with you to read your presence)
* 2. In Discord, connect your Spotify account and enable
* "Display Spotify as your status".
* 3. Put your Discord user ID below (Discord Settings Advanced
* Developer Mode on, then right-click your name Copy User ID).
*/
const POLL_MS = 30000; // refresh every 30s const DISCORD_USER_ID = "1464890289922641993";
(function nowPlaying() { (function nowPlaying() {
const el = document.getElementById("now-playing"); const el = document.getElementById("now-playing");
if (!el) return; if (!el) return;
// Don't fire until configured (keeps the widget hidden on a fresh clone) // Stay hidden until configured (keeps the widget invisible on a fresh clone)
if ( if (!DISCORD_USER_ID || DISCORD_USER_ID === "REPLACE_WITH_YOUR_DISCORD_USER_ID") {
LASTFM_USER === "YOUR_LASTFM_USERNAME" ||
LASTFM_API_KEY === "YOUR_LASTFM_API_KEY"
) {
return; return;
} }
const artEl = el.querySelector(".np-art"); const artEl = el.querySelector(".np-art");
const labelEl = el.querySelector(".np-label"); const labelEl = el.querySelector(".np-label");
const statusLabelEl = el.querySelector(".np-status-label");
const trackEl = el.querySelector(".np-track"); const trackEl = el.querySelector(".np-track");
const artistEl = el.querySelector(".np-artist"); const artistEl = el.querySelector(".np-artist");
const fillEl = el.querySelector(".np-fill");
const curEl = el.querySelector(".np-cur");
const durEl = el.querySelector(".np-dur");
const endpoint = const STATUS_LABELS = {
"https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks" + online: "Online",
`&user=${encodeURIComponent(LASTFM_USER)}` + idle: "Idle",
`&api_key=${encodeURIComponent(LASTFM_API_KEY)}` + dnd: "Do Not Disturb",
"&format=json&limit=1"; offline: "Offline",
};
async function update() { let latest = null; // last presence payload
try { let progressTimer = null; // 1s ticker while a track is playing
const res = await fetch(endpoint); let ws = null;
if (!res.ok) return; let heartbeat = null;
const data = await res.json(); let reconnectDelay = 1000;
const track = data?.recenttracks?.track?.[0];
if (!track) return;
const nowPlaying = track["@attr"]?.nowplaying === "true"; function fmt(ms) {
const name = track.name || ""; const total = Math.max(0, Math.floor(ms / 1000));
const artist = track.artist?.["#text"] || ""; const m = Math.floor(total / 60);
const url = track.url || `https://www.last.fm/user/${LASTFM_USER}`; const s = total % 60;
const images = track.image || []; return `${m}:${String(s).padStart(2, "0")}`;
const art = images[images.length - 1]?.["#text"] || "";
labelEl.textContent = nowPlaying ? "Now playing" : "Last played";
trackEl.textContent = name;
artistEl.textContent = artist;
el.href = url;
el.classList.toggle("is-live", nowPlaying);
if (art) {
artEl.src = art;
artEl.style.display = "";
} else {
artEl.style.display = "none";
}
el.hidden = false;
} catch (e) {
/* network hiccup — keep last state, try again next tick */
}
} }
update(); function clamp(n, lo, hi) {
setInterval(update, POLL_MS); return Math.min(Math.max(n, lo), hi);
}
// ---- snap album-art colour to the active Catppuccin palette ------------
// The accent vars are read live from CSS, so this follows whichever flavour
// (mocha / macchiato / frappe / latte) is currently active.
const ACCENT_VARS = [
"rosewater", "flamingo", "pink", "mauve", "red", "maroon", "peach",
"yellow", "green", "teal", "sky", "saphire", "blue", "lavender",
];
function hexToRgb(hex) {
hex = hex.trim().replace("#", "");
if (hex.length === 3) hex = hex.split("").map((c) => c + c).join("");
const n = parseInt(hex, 16);
return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
}
function getThemePalette() {
const cs = getComputedStyle(document.documentElement);
const pal = [];
for (const name of ACCENT_VARS) {
const v = cs.getPropertyValue("--" + name).trim();
if (v.startsWith("#")) {
const [r, g, b] = hexToRgb(v);
pal.push({ name, r, g, b });
}
}
return pal;
}
// Nearest palette swatch using a redmean-weighted distance (closer to how
// the eye judges colour difference than plain RGB distance).
function nearestAccent(r, g, b) {
const pal = getThemePalette();
let best = null, bestD = Infinity;
for (const c of pal) {
const rm = (r + c.r) / 2;
const dr = r - c.r, dg = g - c.g, db = b - c.b;
const d = (2 + rm / 256) * dr * dr + 4 * dg * dg + (2 + (255 - rm) / 256) * db * db;
if (d < bestD) { bestD = d; best = c; }
}
return best;
}
// ---- album-art accent colour -------------------------------------------
let lastArtUrl = null;
function applyAccent(url) {
if (!url || url === lastArtUrl) return;
lastArtUrl = url;
const img = new Image();
img.crossOrigin = "anonymous";
img.referrerPolicy = "no-referrer";
img.onload = () => {
try {
const c = document.createElement("canvas");
const size = 16;
c.width = size;
c.height = size;
const ctx = c.getContext("2d", { willReadFrequently: true });
ctx.drawImage(img, 0, 0, size, size);
const { data } = ctx.getImageData(0, 0, size, size);
let r = 0, g = 0, b = 0, count = 0;
for (let i = 0; i < data.length; i += 4) {
const a = data[i + 3];
if (a < 125) continue;
// skip near-black/near-white so the tint stays vivid
const lum = 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];
if (lum < 24 || lum > 235) continue;
r += data[i]; g += data[i + 1]; b += data[i + 2]; count++;
}
if (!count) { resetAccent(); return; }
r = Math.round(r / count); g = Math.round(g / count); b = Math.round(b / count);
// Snap the average album colour to the nearest Catppuccin accent
const near = nearestAccent(r, g, b);
const rgb = near ? `${near.r}, ${near.g}, ${near.b}` : `${r}, ${g}, ${b}`;
el.style.setProperty("--np-accent", rgb);
el.classList.add("has-accent");
// Drive the whole page's accent (nav, badges, name, link hovers…)
document.documentElement.style.setProperty("--accent-rgb", rgb);
} catch (e) {
resetAccent(); // tainted canvas / CORS — fall back to theme colour
}
};
img.onerror = resetAccent;
img.src = url;
}
function resetAccent() {
el.classList.remove("has-accent");
el.style.removeProperty("--np-accent");
// Hand the page's accent back to the active theme's pink
document.documentElement.style.removeProperty("--accent-rgb");
}
// ---- rendering ----------------------------------------------------------
function stopProgress() {
if (progressTimer) { clearInterval(progressTimer); progressTimer = null; }
}
function tickProgress(spotify) {
const start = spotify.timestamps && spotify.timestamps.start;
const end = spotify.timestamps && spotify.timestamps.end;
if (!start || !end || end <= start) {
el.classList.remove("has-progress");
return;
}
el.classList.add("has-progress");
const now = Date.now();
const elapsed = clamp(now - start, 0, end - start);
const pct = clamp((elapsed / (end - start)) * 100, 0, 100);
fillEl.style.width = pct + "%";
curEl.textContent = fmt(elapsed);
durEl.textContent = fmt(end - start);
}
function render(d) {
if (!d) return;
const status = d.discord_status || "offline";
el.dataset.status = status;
// Discord status word — always shown (coexists with the track)
statusLabelEl.textContent = STATUS_LABELS[status] || "Offline";
const spotify = d.listening_to_spotify && d.spotify ? d.spotify : null;
if (spotify) {
el.classList.add("is-live");
labelEl.textContent = "Now playing";
trackEl.textContent = spotify.song || "";
artistEl.textContent = spotify.artist || "";
if (spotify.album_art_url) {
artEl.src = spotify.album_art_url;
artEl.style.display = "";
applyAccent(spotify.album_art_url);
} else {
artEl.style.display = "none";
resetAccent();
}
el.href = spotify.track_id
? `https://open.spotify.com/track/${spotify.track_id}`
: "https://open.spotify.com/";
stopProgress();
tickProgress(spotify);
progressTimer = setInterval(() => tickProgress(spotify), 1000);
} else {
// Not listening — just the Discord status (dot + word in the head)
el.classList.remove("is-live", "has-progress");
stopProgress();
resetAccent();
trackEl.textContent = "";
artistEl.textContent = "";
artEl.style.display = "none";
el.href = "https://discord.gg/TransRights";
}
el.hidden = false;
}
// ---- Lanyard websocket --------------------------------------------------
function connect() {
ws = new WebSocket("wss://api.lanyard.rest/socket");
ws.addEventListener("message", (evt) => {
let msg;
try { msg = JSON.parse(evt.data); } catch (e) { return; }
// op 1 = Hello: start heartbeat, then subscribe
if (msg.op === 1) {
const interval = (msg.d && msg.d.heartbeat_interval) || 30000;
if (heartbeat) clearInterval(heartbeat);
heartbeat = setInterval(() => {
if (ws && ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ op: 3 }));
}, interval);
ws.send(JSON.stringify({
op: 2,
d: { subscribe_to_id: DISCORD_USER_ID },
}));
return;
}
// op 0 = Event: INIT_STATE or PRESENCE_UPDATE
if (msg.op === 0) {
const d = msg.t === "INIT_STATE"
? (msg.d && msg.d[DISCORD_USER_ID]) || msg.d
: msg.d;
latest = d;
render(d);
}
});
ws.addEventListener("open", () => { reconnectDelay = 1000; });
ws.addEventListener("close", () => {
if (heartbeat) { clearInterval(heartbeat); heartbeat = null; }
stopProgress();
// exponential backoff up to 30s
setTimeout(connect, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, 30000);
});
ws.addEventListener("error", () => { try { ws.close(); } catch (e) {} });
}
connect();
// keep the progress bar honest when returning to the tab
document.addEventListener("visibilitychange", () => {
if (!document.hidden && latest) render(latest);
});
})(); })();

View File

@ -6,7 +6,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clove Twilight - Tech Stack</title> <title>Clove Twilight - Tech Stack</title>
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg"> <link rel="stylesheet" href="/css/themes/mocha.css">
<link rel="stylesheet" href="/css/themes/macchiato.css">
<link rel="stylesheet" href="/css/themes/frappe.css">
<link rel="stylesheet" href="/css/themes/latte.css">
<script>try { var f = localStorage.getItem('ctpFlavor'); document.documentElement.setAttribute('data-flavor', ['mocha', 'macchiato', 'frappe', 'latte'].indexOf(f) >= 0 ? f : 'mocha'); } catch (e) { document.documentElement.setAttribute('data-flavor', 'mocha'); }</script>
<link rel="icon" type="image/svg+xml" href="/images/favicon/favicon.svg">
<!-- SEO Meta Tags --> <!-- SEO Meta Tags -->
<meta name="description" content="Tech Stack for Clove Twilight" /> <meta name="description" content="Tech Stack for Clove Twilight" />
@ -24,7 +29,7 @@
<meta name="theme-color" content="#f5c2e7" /> <meta name="theme-color" content="#f5c2e7" />
<!-- Open Graph / Discord / Facebook --> <!-- Open Graph / Discord / Facebook -->
<meta property="og:image" content="https://clove.is-a.dev/images/favicon.png" /> <meta property="og:image" content="https://clove.is-a.dev/images/favicon/favicon.png" />
<meta property="og:site_name" content="clove.is-a.dev" /> <meta property="og:site_name" content="clove.is-a.dev" />
<meta property="og:title" content="Clove Twilight | Tech Stack" /> <meta property="og:title" content="Clove Twilight | Tech Stack" />
<meta property="og:description" content="Tech Stack for Clove Twilight" /> <meta property="og:description" content="Tech Stack for Clove Twilight" />
@ -33,7 +38,7 @@
<meta property="og:locale" content="en_GB" /> <meta property="og:locale" content="en_GB" />
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:image" content="https://clove.is-a.dev/images/favicon.png" /> <meta name="twitter:image" content="https://clove.is-a.dev/images/favicon/favicon.png" />
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Clove Twilight | Tech Stack" /> <meta name="twitter:title" content="Clove Twilight | Tech Stack" />
<meta name="twitter:description" content="Tech Stack for Clove Twilight" /> <meta name="twitter:description" content="Tech Stack for Clove Twilight" />
@ -45,254 +50,109 @@
<nav class="nav-links"> <nav class="nav-links">
<a class="nav-link" data-href="/">Link Center</a> <a class="nav-link" data-href="/">Link Center</a>
<a class="nav-link selected" data-href="/tech-stack">Tech Stack</a> <a class="nav-link selected" data-href="/tech-stack">Tech Stack</a>
<a class="nav-link is-a-dev" data-href="https://clove.is-a.dev" target="_blank"
rel="noopener noreferrer">clove.is-a.dev</a>
</nav> </nav>
</header> </header>
<a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden> <a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden>
<img class="np-art" alt="" referrerpolicy="no-referrer"> <img class="np-art" alt="" referrerpolicy="no-referrer" crossorigin="anonymous">
<span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span> <span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
<span class="np-text"> <span class="np-text">
<span class="np-label">Now playing</span> <span class="np-head">
<span class="np-status" aria-hidden="true"></span>
<span class="np-status-label"></span>
<span class="np-label">Now playing</span>
</span>
<span class="np-track"></span> <span class="np-track"></span>
<span class="np-artist"></span> <span class="np-artist"></span>
<span class="np-progress" aria-hidden="true">
<span class="np-bar"><span class="np-fill"></span></span>
<span class="np-times"><span class="np-cur">0:00</span><span class="np-dur">0:00</span></span>
</span>
</span> </span>
</a> </a>
<a class="version-tag" data-href="/changelog" title="Changelog">v1.4.0</a>
<main class="hub"> <main class="hub">
<header class="hub-header"> <header class="hub-header">
<img class="pfp" src="/images/avatar.png" alt="Clove Twilight avatar"> <img class="pfp" src="/images/favicon/avatar.png" alt="Clove Twilight avatar">
<h1>Clove Twilight</h1> <h1>Clove Twilight</h1>
<h2 class="pronouns">(fae/faer)</h2> <h2 class="pronouns">(fae/faer)</h2>
<p class="tagline">Tech Stack</p> <p class="tagline">Tech Stack</p>
</header> </header>
<section class="tech-stack" aria-label="Tech stack"> <section class="tech-stack" aria-label="Tech stack">
<img class="tech-badge" <span class="tech-icon pink" style="--si:url('https://cdn.simpleicons.org/javascript')" role="img" aria-label="JavaScript"></span>
src="https://img.shields.io/badge/JavaScript-313244?style=flat-square&labelColor=1e1e2e&logo=javascript&logoColor=f5c2e7" <span class="tech-icon mauve" style="--si:url('https://cdn.simpleicons.org/openjdk')" role="img" aria-label="Java"></span>
alt="JavaScript" loading="lazy"> <span class="tech-icon lavender" style="--si:url('https://cdn.simpleicons.org/html5')" role="img" aria-label="HTML5"></span>
<img class="tech-badge" <span class="tech-icon blue" style="--si:url('https://cdn.simpleicons.org/markdown')" role="img" aria-label="Markdown"></span>
src="https://img.shields.io/badge/Java-313244?style=flat-square&labelColor=1e1e2e&logo=openjdk&logoColor=cba6f7" <span class="tech-icon teal" style="--si:url('https://cdn.simpleicons.org/latex')" role="img" aria-label="LaTeX"></span>
alt="Java" loading="lazy"> <span class="tech-icon peach" style="--si:url('https://cdn.simpleicons.org/typescript')" role="img" aria-label="TypeScript"></span>
<img class="tech-badge" <span class="tech-icon yellow" style="--si:url('https://cdn.simpleicons.org/gnubash')" role="img" aria-label="Bash Script"></span>
src="https://img.shields.io/badge/HTML5-313244?style=flat-square&labelColor=1e1e2e&logo=html5&logoColor=b4befe" <span class="tech-icon red" style="--si:url('https://cdn.simpleicons.org/python')" role="img" aria-label="Python"></span>
alt="HTML5" loading="lazy"> <span class="tech-icon sapphire" style="--si:url('https://cdn.simpleicons.org/cloudflare')" role="img" aria-label="Cloudflare"></span>
<img class="tech-badge" <span class="tech-icon mauve" style="--si:url('https://cdn.simpleicons.org/vercel')" role="img" aria-label="Vercel"></span>
src="https://img.shields.io/badge/Markdown-313244?style=flat-square&labelColor=1e1e2e&logo=markdown&logoColor=89b4fa" <span class="tech-icon lavender" style="--si:url('https://cdn.simpleicons.org/bootstrap')" role="img" aria-label="Bootstrap"></span>
alt="Markdown" loading="lazy"> <span class="tech-icon blue" style="--si:url('https://cdn.simpleicons.org/ejs')" role="img" aria-label="EJS"></span>
<img class="tech-badge" <span class="tech-icon teal" style="--si:url('https://cdn.simpleicons.org/electron')" role="img" aria-label="Electron.js"></span>
src="https://img.shields.io/badge/LaTeX-313244?style=flat-square&labelColor=1e1e2e&logo=latex&logoColor=94e2d5" <span class="tech-icon green" style="--si:url('https://cdn.simpleicons.org/express')" role="img" aria-label="Express.js"></span>
alt="LaTeX" loading="lazy"> <span class="tech-icon peach" style="--si:url('https://cdn.simpleicons.org/fastapi')" role="img" aria-label="FastAPI"></span>
<img class="tech-badge" <span class="tech-icon red" style="--si:url('https://cdn.simpleicons.org/insomnia')" role="img" aria-label="Insomnia"></span>
src="https://img.shields.io/badge/Windows%20Terminal-313244?style=flat-square&labelColor=1e1e2e&logo=windows-terminal&logoColor=a6e3a1" <span class="tech-icon maroon" style="--si:url('https://cdn.simpleicons.org/jsonwebtokens')" role="img" aria-label="JWT"></span>
alt="Windows Terminal" loading="lazy"> <span class="tech-icon sapphire" style="--si:url('https://cdn.simpleicons.org/npm')" role="img" aria-label="NPM"></span>
<img class="tech-badge" <span class="tech-icon rosewater" style="--si:url('https://cdn.simpleicons.org/nextdotjs')" role="img" aria-label="Next JS"></span>
src="https://img.shields.io/badge/TypeScript-313244?style=flat-square&labelColor=1e1e2e&logo=typescript&logoColor=fab387" <span class="tech-icon pink" style="--si:url('https://cdn.simpleicons.org/nodedotjs')" role="img" aria-label="NodeJS"></span>
alt="TypeScript" loading="lazy"> <span class="tech-icon mauve" style="--si:url('https://cdn.simpleicons.org/nodemon')" role="img" aria-label="Nodemon"></span>
<img class="tech-badge" <span class="tech-icon lavender" style="--si:url('https://cdn.simpleicons.org/pnpm')" role="img" aria-label="PNPM"></span>
src="https://img.shields.io/badge/Bash%20Script-313244?style=flat-square&labelColor=1e1e2e&logo=gnu-bash&logoColor=f9e2af" <span class="tech-icon blue" style="--si:url('https://cdn.simpleicons.org/react')" role="img" aria-label="React"></span>
alt="Bash Script" loading="lazy"> <span class="tech-icon red" style="--si:url('https://cdn.simpleicons.org/tailwindcss')" role="img" aria-label="TailwindCSS"></span>
<img class="tech-badge" <span class="tech-icon maroon" style="--si:url('https://cdn.simpleicons.org/vite')" role="img" aria-label="Vite"></span>
src="https://img.shields.io/badge/Python-313244?style=flat-square&labelColor=1e1e2e&logo=python&logoColor=f38ba8" <span class="tech-icon sapphire" style="--si:url('https://cdn.simpleicons.org/vuedotjs')" role="img" aria-label="Vue.js"></span>
alt="Python" loading="lazy"> <span class="tech-icon rosewater" style="--si:url('https://cdn.simpleicons.org/wordpress')" role="img" aria-label="WordPress"></span>
<img class="tech-badge" <span class="tech-icon mauve" style="--si:url('https://cdn.simpleicons.org/nginx')" role="img" aria-label="Nginx"></span>
src="https://img.shields.io/badge/PowerShell-313244?style=flat-square&labelColor=1e1e2e&logo=powershell&logoColor=89dceb" <span class="tech-icon lavender" style="--si:url('https://cdn.simpleicons.org/mysql')" role="img" aria-label="MySQL"></span>
alt="PowerShell" loading="lazy"> <span class="tech-icon blue" style="--si:url('https://cdn.simpleicons.org/sqlite')" role="img" aria-label="SQLite"></span>
<img class="tech-badge" <span class="tech-icon teal" style="--si:url('https://cdn.simpleicons.org/postgresql')" role="img" aria-label="Postgres"></span>
src="https://img.shields.io/badge/PHP-313244?style=flat-square&labelColor=1e1e2e&logo=php&logoColor=eba0ac" <span class="tech-icon green" style="--si:url('https://cdn.simpleicons.org/redis')" role="img" aria-label="Redis"></span>
alt="PHP" loading="lazy"> <span class="tech-icon red" style="--si:url('https://cdn.simpleicons.org/inkscape')" role="img" aria-label="Inkscape"></span>
<img class="tech-badge" <span class="tech-icon sky" style="--si:url('https://cdn.simpleicons.org/github')" role="img" aria-label="GitHub"></span>
src="https://img.shields.io/badge/Cloudflare-313244?style=flat-square&labelColor=1e1e2e&logo=Cloudflare&logoColor=74c7ec" <span class="tech-icon maroon" style="--si:url('https://cdn.simpleicons.org/githubactions')" role="img" aria-label="GitHub Actions"></span>
alt="Cloudflare" loading="lazy"> <span class="tech-icon sapphire" style="--si:url('https://cdn.simpleicons.org/git')" role="img" aria-label="Git"></span>
<img class="tech-badge" <span class="tech-icon rosewater" style="--si:url('https://cdn.simpleicons.org/gitea')" role="img" aria-label="Gitea"></span>
src="https://img.shields.io/badge/Heroku-313244?style=flat-square&labelColor=1e1e2e&logo=heroku&logoColor=f5e0dc" <span class="tech-icon pink" style="--si:url('https://cdn.simpleicons.org/arduino')" role="img" aria-label="Arduino"></span>
alt="Heroku" loading="lazy"> <span class="tech-icon lavender" style="--si:url('https://cdn.simpleicons.org/docker')" role="img" aria-label="Docker"></span>
<img class="tech-badge" <span class="tech-icon blue" style="--si:url('https://cdn.simpleicons.org/eslint')" role="img" aria-label="ESLint"></span>
src="https://img.shields.io/badge/Linode-313244?style=flat-square&labelColor=1e1e2e&logo=linode&logoColor=f5c2e7" <span class="tech-icon teal" style="--si:url('https://cdn.simpleicons.org/ffmpeg')" role="img" aria-label="FFmpeg"></span>
alt="Linode" loading="lazy"> <span class="tech-icon green" style="--si:url('https://cdn.simpleicons.org/gradle')" role="img" aria-label="Gradle"></span>
<img class="tech-badge" <span class="tech-icon red" style="--si:url('https://cdn.simpleicons.org/raspberrypi')" role="img" aria-label="Raspberry Pi"></span>
src="https://img.shields.io/badge/Vercel-313244?style=flat-square&labelColor=1e1e2e&logo=vercel&logoColor=cba6f7" <span class="tech-icon blue" style="--si:url('https://cdn.simpleicons.org/vscodium')" role="img" aria-label="VSCodium"></span>
alt="Vercel" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Bootstrap-313244?style=flat-square&labelColor=1e1e2e&logo=bootstrap&logoColor=b4befe"
alt="Bootstrap" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/EJS-313244?style=flat-square&labelColor=1e1e2e&logo=ejs&logoColor=89b4fa"
alt="EJS" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Electron.js-313244?style=flat-square&labelColor=1e1e2e&logo=Electron&logoColor=94e2d5"
alt="Electron.js" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Express.js-313244?style=flat-square&labelColor=1e1e2e&logo=express&logoColor=a6e3a1"
alt="Express.js" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/FastAPI-313244?style=flat-square&labelColor=1e1e2e&logo=fastapi&logoColor=fab387"
alt="FastAPI" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Flask-313244?style=flat-square&labelColor=1e1e2e&logo=flask&logoColor=f9e2af"
alt="Flask" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Insomnia-313244?style=flat-square&labelColor=1e1e2e&logo=insomnia&logoColor=f38ba8"
alt="Insomnia" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/jQuery-313244?style=flat-square&labelColor=1e1e2e&logo=jquery&logoColor=89dceb"
alt="jQuery" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/JWT-313244?style=flat-square&labelColor=1e1e2e&logo=JSON%20web%20tokens&logoColor=eba0ac"
alt="JWT" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/NPM-313244?style=flat-square&labelColor=1e1e2e&logo=npm&logoColor=74c7ec"
alt="NPM" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Next%20JS-313244?style=flat-square&labelColor=1e1e2e&logo=next.js&logoColor=f5e0dc"
alt="Next JS" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/NodeJS-313244?style=flat-square&labelColor=1e1e2e&logo=node.js&logoColor=f5c2e7"
alt="NodeJS" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Nodemon-313244?style=flat-square&labelColor=1e1e2e&logo=nodemon&logoColor=cba6f7"
alt="Nodemon" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/PNPM-313244?style=flat-square&labelColor=1e1e2e&logo=pnpm&logoColor=b4befe"
alt="PNPM" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/React-313244?style=flat-square&labelColor=1e1e2e&logo=react&logoColor=89b4fa"
alt="React" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/React%20Native-313244?style=flat-square&labelColor=1e1e2e&logo=react&logoColor=94e2d5"
alt="React Native" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/React%20Query-313244?style=flat-square&labelColor=1e1e2e&logo=react%20query&logoColor=a6e3a1"
alt="React Query" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/React%20Hook%20Form-313244?style=flat-square&labelColor=1e1e2e&logo=reacthookform&logoColor=fab387"
alt="React Hook Form" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/React%20Router-313244?style=flat-square&labelColor=1e1e2e&logo=react-router&logoColor=f9e2af"
alt="React Router" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/TailwindCSS-313244?style=flat-square&labelColor=1e1e2e&logo=tailwind-css&logoColor=f38ba8"
alt="TailwindCSS" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Three%20js-313244?style=flat-square&labelColor=1e1e2e&logo=three.js&logoColor=89dceb"
alt="Three js" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Vite-313244?style=flat-square&labelColor=1e1e2e&logo=vite&logoColor=eba0ac"
alt="Vite" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Vue.js-313244?style=flat-square&labelColor=1e1e2e&logo=vuedotjs&logoColor=74c7ec"
alt="Vue.js" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/WordPress-313244?style=flat-square&labelColor=1e1e2e&logo=WordPress&logoColor=f5e0dc"
alt="WordPress" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Yarn-313244?style=flat-square&labelColor=1e1e2e&logo=yarn&logoColor=f5c2e7"
alt="Yarn" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Nginx-313244?style=flat-square&labelColor=1e1e2e&logo=nginx&logoColor=cba6f7"
alt="Nginx" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/MySQL-313244?style=flat-square&labelColor=1e1e2e&logo=mysql&logoColor=b4befe"
alt="MySQL" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/SQLite-313244?style=flat-square&labelColor=1e1e2e&logo=sqlite&logoColor=89b4fa"
alt="SQLite" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Postgres-313244?style=flat-square&labelColor=1e1e2e&logo=postgresql&logoColor=94e2d5"
alt="Postgres" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Redis-313244?style=flat-square&labelColor=1e1e2e&logo=redis&logoColor=a6e3a1"
alt="Redis" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Adobe%20Photoshop-313244?style=flat-square&labelColor=1e1e2e&logo=adobe%20photoshop&logoColor=fab387"
alt="Adobe Photoshop" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Canva-313244?style=flat-square&labelColor=1e1e2e&logo=Canva&logoColor=f9e2af"
alt="Canva" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Inkscape-313244?style=flat-square&labelColor=1e1e2e&logo=inkscape&logoColor=f38ba8"
alt="Inkscape" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/GitHub-313244?style=flat-square&labelColor=1e1e2e&logo=github&logoColor=89dceb"
alt="GitHub" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/GitHub%20Actions-313244?style=flat-square&labelColor=1e1e2e&logo=githubactions&logoColor=eba0ac"
alt="GitHub Actions" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Git-313244?style=flat-square&labelColor=1e1e2e&logo=git&logoColor=74c7ec"
alt="Git" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Gitea-313244?style=flat-square&labelColor=1e1e2e&logo=gitea&logoColor=f5e0dc"
alt="Gitea" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Arduino-313244?style=flat-square&labelColor=1e1e2e&logo=Arduino&logoColor=f5c2e7"
alt="Arduino" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Cisco-313244?style=flat-square&labelColor=1e1e2e&logo=cisco&logoColor=cba6f7"
alt="Cisco" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Docker-313244?style=flat-square&labelColor=1e1e2e&logo=docker&logoColor=b4befe"
alt="Docker" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/ESLint-313244?style=flat-square&labelColor=1e1e2e&logo=eslint&logoColor=89b4fa"
alt="ESLint" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/FFmpeg-313244?style=flat-square&labelColor=1e1e2e&logo=ffmpeg&logoColor=94e2d5"
alt="FFmpeg" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Gradle-313244?style=flat-square&labelColor=1e1e2e&logo=Gradle&logoColor=a6e3a1"
alt="Gradle" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Grafana-313244?style=flat-square&labelColor=1e1e2e&logo=grafana&logoColor=fab387"
alt="Grafana" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/OpenAPI%20Specification-313244?style=flat-square&labelColor=1e1e2e&logo=openapiinitiative&logoColor=f9e2af"
alt="OpenAPI Specification" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Raspberry%20Pi-313244?style=flat-square&labelColor=1e1e2e&logo=Raspberry-Pi&logoColor=f38ba8"
alt="Raspberry Pi" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Postman-313244?style=flat-square&labelColor=1e1e2e&logo=postman&logoColor=89dceb"
alt="Postman" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Swagger-313244?style=flat-square&labelColor=1e1e2e&logo=swagger&logoColor=eba0ac"
alt="Swagger" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/TOR-313244?style=flat-square&labelColor=1e1e2e&logo=tor-project&logoColor=74c7ec"
alt="TOR" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/AMD-313244?style=flat-square&labelColor=1e1e2e&logo=amd&logoColor=f5e0dc"
alt="AMD" loading="lazy">
<img class="tech-badge"
src="https://img.shields.io/badge/Epic%20Games-313244?style=flat-square&labelColor=1e1e2e&logo=epicgames&logoColor=f5c2e7"
alt="Epic Games" loading="lazy">
</section> </section>
</main> </main>
<aside class="badges" aria-label="System badges"> <aside class="badges" aria-label="System badges">
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/amd.svg" alt=""> <img class="badge-icon" src="/images/misc/amd.svg" alt="">
AMD Purist AMD Purist
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/arch.svg" alt=""> <img class="badge-icon" src="/images/misc/arch.svg" alt="">
I use arch btw I use arch btw
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/debian.svg" alt=""> <img class="badge-icon" src="/images/misc/debian.svg" alt="">
Debian Professional Debian Professional
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/apple.svg" alt=""> <img class="badge-icon" src="/images/misc/apple.svg" alt="">
Apple Ecosystem Enthusiast Apple Ecosystem Enthusiast
</span> </span>
</aside> </aside>
<script src="/js/cat.js" data-cat="/images/oneko.gif"></script> <script src="/js/cat.js" data-cat="/images/misc/oneko.gif"></script>
<script src="/js/nav.js"></script> <script src="/js/nav.js"></script>
<script src="/js/now-playing.js"></script> <script src="/js/now-playing.js"></script>
<script src="/js/cat-modes.js"></script> <script src="/js/flavors.js"></script>
<script src="/js/site-switcher.js"></script>
</body> </body>
</html> </html>

View File

@ -6,7 +6,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clove Twilight - Template</title> <title>Clove Twilight - Template</title>
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg"> <link rel="stylesheet" href="/css/themes/mocha.css">
<link rel="stylesheet" href="/css/themes/macchiato.css">
<link rel="stylesheet" href="/css/themes/frappe.css">
<link rel="stylesheet" href="/css/themes/latte.css">
<script>try { var f = localStorage.getItem('ctpFlavor'); document.documentElement.setAttribute('data-flavor', ['mocha', 'macchiato', 'frappe', 'latte'].indexOf(f) >= 0 ? f : 'mocha'); } catch (e) { document.documentElement.setAttribute('data-flavor', 'mocha'); }</script>
<link rel="icon" type="image/svg+xml" href="/images/favicon/favicon.svg">
<!-- SEO Meta Tags --> <!-- SEO Meta Tags -->
<meta name="description" content="Template Page for Clove Twilight" /> <meta name="description" content="Template Page for Clove Twilight" />
@ -43,42 +48,66 @@
<header class="nav"> <header class="nav">
<nav class="nav-links"> <nav class="nav-links">
<a class="nav-link" data-href="/">Link Center</a>
<a class="nav-link selected" data-href="/template">Template</a> <a class="nav-link selected" data-href="/template">Template</a>
</nav> </nav>
</header> </header>
<a class="now-playing" id="now-playing" target="_blank" rel="noopener" hidden>
<img class="np-art" alt="" referrerpolicy="no-referrer" crossorigin="anonymous">
<span class="np-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
<span class="np-text">
<span class="np-head">
<span class="np-status" aria-hidden="true"></span>
<span class="np-status-label"></span>
<span class="np-label">Now playing</span>
</span>
<span class="np-track"></span>
<span class="np-artist"></span>
<span class="np-progress" aria-hidden="true">
<span class="np-bar"><span class="np-fill"></span></span>
<span class="np-times"><span class="np-cur">0:00</span><span class="np-dur">0:00</span></span>
</span>
</span>
</a>
<main class="hub"> <main class="hub">
<header class="hub-header"> <header class="hub-header">
<img class="pfp" src="/images/avatar.png" alt="Clove Twilight avatar"> <img class="pfp" src="/images/favicon/avatar.png" alt="Clove Twilight avatar">
<h1>Clove Twilight</h1> <h1>Clove Twilight</h1>
<h2 class="pronouns">(fae/faer)</h2> <h2 class="pronouns">(fae/faer)</h2>
<p class="tagline">Template</p> <p class="tagline">Template</p>
</header> </header>
<h1>Template</h1> <h1>Template</h1>
<p>This is a simple template for the clove.is-a.dev website, it's to make it easier for myself to create new <p>This is a simple template for the clove.is-a.dev website, it's to make it easier for myself to create
new
pages.</p> pages.</p>
</main> </main>
<aside class="badges" aria-label="System badges"> <aside class="badges" aria-label="System badges">
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/amd.svg" alt=""> <img class="badge-icon" src="/images/misc/amd.svg" alt="">
AMD Purist AMD Purist
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/arch.svg" alt=""> <img class="badge-icon" src="/images/misc/arch.svg" alt="">
I use arch btw I use arch btw
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/debian.svg" alt=""> <img class="badge-icon" src="/images/misc/debian.svg" alt="">
Debian Professional Debian Professional
</span> </span>
<span class="badge"> <span class="badge">
<img class="badge-icon" src="/images/apple.svg" alt=""> <img class="badge-icon" src="/images/misc/apple.svg" alt="">
Apple Ecosystem Enthusiast Apple Ecosystem Enthusiast
</span> </span>
</aside> </aside>
<script src="/js/cat.js" data-cat="/images/oneko.gif"></script> <script src="/js/cat.js" data-cat="/images/misc/oneko.gif"></script>
<script src="/js/nav.js"></script> <script src="/js/nav.js"></script>
<script src="/js/now-playing.js"></script>
<script src="/js/flavors.js"></script>
<script src="/js/site-switcher.js"></script>
</body> </body>
</html> </html>