themes-y2k/css.go
Alex Dunmow 49f9c90589 initial: theme plugin y2k
Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously
an unversioned directory inside ~/src/blockninja-themes/y2k.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 14:11:46 +08:00

229 lines
6.2 KiB
Go

package main
// y2kInputCSS is appended to the host Tailwind input. It declares the chrome
// gradient stops, mesh anchors, bevel shadows, marquee/sparkle/metaball
// keyframes, and the utility classes those keyframes drive. Every colour is
// expressed through theme HSL custom properties (no hardcoded hex/rgb).
const y2kInputCSS = `
/* === y2k theme — chrome/bevel/mesh tokens === */
:root {
--chrome-1: 280 30% 95%;
--chrome-2: 200 40% 75%;
--chrome-3: 320 60% 60%;
--chrome-4: 280 40% 25%;
--mesh-a: 320 95% 58%;
--mesh-b: 185 90% 60%;
--mesh-c: 60 95% 70%;
--bevel-light: 0 0% 100%;
--bevel-dark: 280 60% 12%;
}
.dark {
--chrome-1: 280 30% 30%;
--chrome-2: 200 40% 45%;
--chrome-3: 320 60% 50%;
--chrome-4: 280 40% 10%;
--mesh-a: 320 100% 65%;
--mesh-b: 185 95% 55%;
--mesh-c: 60 100% 65%;
--bevel-light: 0 0% 100%;
--bevel-dark: 280 80% 4%;
}
/* === keyframes === */
@keyframes marquee-x {
from { transform: translate3d(0, 0, 0); }
to { transform: translate3d(-50%, 0, 0); }
}
@keyframes sparkle {
0%, 100% { opacity: 0; transform: scale(0.5) rotate(0deg); }
50% { opacity: 1; transform: scale(1) rotate(180deg); }
}
@keyframes metaball-morph {
0%, 100% { d: path("M 50 100 a 50 50 0 1 1 100 0 a 50 50 0 1 1 -100 0"); }
50% { d: path("M 40 95 a 60 55 0 1 1 120 5 a 55 60 0 1 1 -120 -5"); }
}
/* === chrome surface utilities === */
.y2k-chrome-bg {
background-image:
linear-gradient(180deg,
hsl(var(--chrome-1)) 0%,
hsl(var(--chrome-2)) 35%,
hsl(var(--chrome-3)) 70%,
hsl(var(--chrome-4)) 100%);
}
.y2k-mesh-bg {
background-image:
radial-gradient(at 20% 20%, hsl(var(--mesh-a) / 0.85) 0%, transparent 55%),
radial-gradient(at 80% 30%, hsl(var(--mesh-b) / 0.80) 0%, transparent 55%),
radial-gradient(at 50% 80%, hsl(var(--mesh-c) / 0.70) 0%, transparent 55%),
linear-gradient(135deg, hsl(var(--background)) 0%, hsl(var(--card)) 100%);
}
.y2k-bevel {
border: 2px solid hsl(var(--border));
box-shadow:
inset 0 1px 0 hsl(var(--bevel-light) / 0.85),
inset 0 -2px 0 hsl(var(--bevel-dark) / 0.35),
0 2px 6px hsl(var(--bevel-dark) / 0.30);
}
.y2k-bevel:active {
box-shadow:
inset 0 2px 4px hsl(var(--bevel-dark) / 0.45),
inset 0 -1px 0 hsl(var(--bevel-light) / 0.40);
}
.y2k-glow {
box-shadow: 0 0 24px hsl(var(--primary) / 0.45);
}
/* === marquee === */
.y2k-marquee {
overflow: hidden;
position: relative;
border-top: 2px solid hsl(var(--border));
border-bottom: 2px solid hsl(var(--border));
}
.y2k-marquee-track {
display: inline-flex;
gap: 3rem;
white-space: nowrap;
animation-name: marquee-x;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.y2k-marquee-track[data-speed="slow"] { animation-duration: 60s; }
.y2k-marquee-track[data-speed="medium"] { animation-duration: 30s; }
.y2k-marquee-track[data-speed="fast"] { animation-duration: 12s; }
.y2k-marquee:hover .y2k-marquee-track,
.y2k-marquee:focus-within .y2k-marquee-track {
animation-play-state: paused;
}
/* === sparkle decoration === */
.y2k-sparkle {
pointer-events: none;
animation: sparkle 1.6s ease-in-out infinite;
}
/* === metaball morph === */
.y2k-metaball {
animation: metaball-morph 6s ease-in-out infinite;
}
/* === webring 88x31 badge === */
.y2k-webring-badge {
display: inline-block;
width: 88px;
height: 31px;
line-height: 31px;
text-align: center;
font-size: 11px;
letter-spacing: 0.05em;
text-transform: uppercase;
border: 1px solid hsl(var(--border));
background-image: linear-gradient(180deg, hsl(var(--chrome-1)) 0%, hsl(var(--chrome-3)) 100%);
color: hsl(var(--primaryForeground));
text-decoration: none;
box-shadow: inset 0 1px 0 hsl(var(--bevel-light) / 0.6);
}
/* === holographic foil for NFT gallery === */
.y2k-foil {
position: relative;
isolation: isolate;
}
.y2k-foil::after {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0;
transition: opacity 220ms ease;
background-image: conic-gradient(
from 0deg,
hsl(var(--mesh-a) / 0.45),
hsl(var(--mesh-b) / 0.45),
hsl(var(--mesh-c) / 0.45),
hsl(var(--mesh-a) / 0.45)
);
mix-blend-mode: color-dodge;
filter: hue-rotate(0deg);
}
.y2k-foil:hover::after,
.y2k-foil:focus-within::after {
opacity: 1;
filter: hue-rotate(45deg);
}
/* === plastic button override === */
.y2k-button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.65rem 1.25rem;
font-weight: 600;
border: 2px solid hsl(var(--border));
border-radius: 0.625rem;
background-image: linear-gradient(180deg,
hsl(var(--primary) / 0.95) 0%,
hsl(var(--primary)) 50%,
hsl(var(--primary) / 0.85) 100%);
color: hsl(var(--primaryForeground));
box-shadow:
inset 0 1px 0 hsl(var(--bevel-light) / 0.7),
inset 0 -2px 0 hsl(var(--bevel-dark) / 0.3),
0 2px 6px hsl(var(--bevel-dark) / 0.25);
transition: transform 90ms ease, box-shadow 90ms ease;
}
.y2k-button:hover { transform: translateY(-1px); }
.y2k-button:active {
transform: translateY(1px);
box-shadow:
inset 0 2px 4px hsl(var(--bevel-dark) / 0.45),
inset 0 -1px 0 hsl(var(--bevel-light) / 0.30);
}
.y2k-button:focus-visible {
outline: 2px solid hsl(var(--ring));
outline-offset: 2px;
}
/* === image chrome frame === */
.y2k-image-frame {
border-radius: 0.625rem;
border: 2px solid hsl(var(--border));
box-shadow:
inset 0 1px 0 hsl(var(--bevel-light) / 0.5),
0 4px 14px hsl(var(--bevel-dark) / 0.35);
}
/* === heading chrome stroke === */
.y2k-heading {
font-family: var(--font-heading, "Stretch Pro", "VT323", "Courier New", monospace);
letter-spacing: 0.04em;
text-shadow:
0 1px 0 hsl(var(--bevel-light) / 0.65),
0 2px 0 hsl(var(--bevel-dark) / 0.35),
0 6px 22px hsl(var(--primary) / 0.45);
}
/* === text holographic link underline === */
.y2k-text a {
background-image: linear-gradient(90deg,
hsl(var(--mesh-a)),
hsl(var(--mesh-b)),
hsl(var(--mesh-c)));
background-size: 100% 2px;
background-repeat: no-repeat;
background-position: 0 100%;
text-decoration: none;
}
/* === reduced motion overrides === */
@media (prefers-reduced-motion: reduce) {
.y2k-marquee-track,
.y2k-sparkle,
.y2k-metaball {
animation: none !important;
}
}
`