rainbow quox
This commit is contained in:
parent
6681d2eefb
commit
da06033eed
45 changed files with 646 additions and 4 deletions
10
Makefile
10
Makefile
|
@ -1,10 +1,12 @@
|
|||
CSS = $(wildcard style/*.css) $(shell find fonts -type f)
|
||||
PAGES = index.html pubkey.txt
|
||||
CSS = $(wildcard style/*.css) $(shell find fonts -type f) \
|
||||
rainbow-quox/style.css
|
||||
PAGES = index.html pubkey.txt rainbow-quox/index.html
|
||||
MEDIA = \
|
||||
$(wildcard media/*.png) $(wildcard media/*.gif) $(wildcard media/*.webp) \
|
||||
$(wildcard media/flags/*) $(wildcard media/buttons/*) \
|
||||
$(wildcard media/icons/*) $(wildcard media/bg/*) 8831.png 8831-quox.png
|
||||
SCRIPTS = $(patsubst %.ts,%.js,$(wildcard script/*.ts))
|
||||
$(wildcard media/icons/*) $(wildcard media/bg/*) 8831.png 8831-quox.png \
|
||||
$(wildcard rainbow-quox/front/*) $(wildcard rainbow-quox/back/*)
|
||||
SCRIPTS = $(patsubst %.ts,%.js,$(wildcard script/*.ts)) rainbow-quox/colour.js
|
||||
MISC = $(shell find .well-known -type f)
|
||||
ALL = $(CSS) $(PAGES) $(MEDIA) $(SCRIPTS) $(MISC)
|
||||
|
||||
|
|
BIN
rainbow-quox/back/belly1.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/belly1.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/belly2.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/belly2.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/claws.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/claws.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/cuffs.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/cuffs.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/eyes.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/eyes.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/fins1.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/fins1.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/fins2.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/fins2.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/fins3.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/fins3.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/lines.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/lines.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/masks.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/masks.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/outer.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/outer.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/spines.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/spines.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/static.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/static.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/stripes.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/stripes.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo1.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo1.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo2.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo2.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo3.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo3.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo4.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo4.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
290
rainbow-quox/colour.ts
Normal file
290
rainbow-quox/colour.ts
Normal file
|
@ -0,0 +1,290 @@
|
|||
type Rand = () => number;
|
||||
|
||||
|
||||
/*
|
||||
let randomData = new Uint32Array(100);
|
||||
let next: number = 0;
|
||||
function reset() { self.crypto.getRandomValues(randomData); next = 0; }
|
||||
function rand() {
|
||||
if (next >= 100) { reset(); }
|
||||
return randomData[next++] / 4_294_967_295; // u32 max
|
||||
}
|
||||
reset();
|
||||
*/
|
||||
|
||||
const rand: Rand = Math.random; // [todo]
|
||||
|
||||
const max = Math.max;
|
||||
const min = Math.min;
|
||||
|
||||
type Oklch = { l: number, c: number, h: number };
|
||||
|
||||
type LD = 'light' | 'dark';
|
||||
|
||||
const MAXL = 0.9;
|
||||
const MINL = 0.4;
|
||||
const MINL_LIGHT = 0.7;
|
||||
const MAXL_DARK = 0.65;
|
||||
|
||||
const MINC_LIGHT = 0.08;
|
||||
const MAXC_LIGHT = 0.125;
|
||||
const MINC_DARK = 0.12;
|
||||
const MAXC_DARK = 0.2;
|
||||
|
||||
// max spread for a sequence of analogous colours. unless that would put them
|
||||
// too close together
|
||||
const MAXH_WIDTH = 80;
|
||||
|
||||
// minimum distance between adjacent analogous colours
|
||||
const MINH_SEP = 5;
|
||||
|
||||
// how far away from 180° a "complementary" colour can be
|
||||
const MAXH_COMPL = 40;
|
||||
|
||||
// how far away from 120° a "triad" colour can be
|
||||
const MAXH_TRIAD = 20;
|
||||
|
||||
function randBetween(x: number, y: number): number {
|
||||
const lo = min(x, y), hi = max(x, y);
|
||||
return lo + rand() * (hi - lo);
|
||||
}
|
||||
|
||||
function oneOf<A>(...xs: A[]): A {
|
||||
return xs[Math.floor(rand() * xs.length)]!;
|
||||
}
|
||||
|
||||
|
||||
function isLight(l: number): boolean { return l >= MINL_LIGHT; }
|
||||
|
||||
function baseLuma(ld?: LD): number {
|
||||
if (ld == 'light') {
|
||||
return randBetween(MINL_LIGHT, MAXL);
|
||||
} else if (ld == 'dark') {
|
||||
return randBetween(MINL, MAXL_DARK);
|
||||
} else {
|
||||
return randBetween(MINL, MAXL);
|
||||
}
|
||||
}
|
||||
|
||||
function baseChroma(l: number): number {
|
||||
if (l >= MINL_LIGHT) {
|
||||
return randBetween(MINC_LIGHT, MAXC_LIGHT);
|
||||
} else {
|
||||
return randBetween(MINC_DARK, MAXC_DARK);
|
||||
}
|
||||
}
|
||||
|
||||
function baseHue(): number { return rand() * 360; }
|
||||
|
||||
function baseOklch(ld?: LD): Oklch {
|
||||
const l = baseLuma(ld);
|
||||
return {l, c: baseChroma(l), h: baseHue()};
|
||||
}
|
||||
|
||||
function lightFor(baseL: number): number {
|
||||
return randBetween(baseL, MAXL);
|
||||
}
|
||||
function darkFor(baseL: number): number {
|
||||
return randBetween(MINL, baseL);
|
||||
}
|
||||
|
||||
function brightFor(l: number, baseC: number): number {
|
||||
if (isLight(l)) { return randBetween(baseC, MAXC_LIGHT); }
|
||||
else { return randBetween(baseC, MAXC_DARK); }
|
||||
}
|
||||
|
||||
function dullFor(l: number, baseC: number): number {
|
||||
if (isLight(l)) { return randBetween(baseC, MINC_LIGHT); }
|
||||
else { return randBetween(baseC, MINC_DARK); }
|
||||
}
|
||||
|
||||
|
||||
type Numbers = number[];
|
||||
|
||||
function upto(end: number): Numbers {
|
||||
function* go(next: number): Iterable<number> {
|
||||
if (next < end) { yield next; yield* go(next+1) }
|
||||
}
|
||||
return Array.from(go(0));
|
||||
}
|
||||
|
||||
function analogous(baseH: number, count: number): Numbers {
|
||||
const minWidth = count * MINH_SEP;
|
||||
const width =
|
||||
MAXH_WIDTH < minWidth ? minWidth : randBetween(minWidth, MAXH_WIDTH);
|
||||
const sep = width / (count - 1);
|
||||
const start = baseH - (width / 2);
|
||||
let numbers = Array.from(upto(count).map(i => start + i * sep));
|
||||
return rand() > 0.5 ? numbers : numbers.reverse();
|
||||
}
|
||||
|
||||
function complementary(baseH: number, count: number): Numbers {
|
||||
const angle = randBetween(180 - MAXH_COMPL, 180 + MAXH_COMPL);
|
||||
return analogous(baseH + angle, count);
|
||||
}
|
||||
|
||||
function triad(baseH: number): [number, number] {
|
||||
const angle = randBetween(120 - MAXH_TRIAD, 120 + MAXH_TRIAD);
|
||||
return [baseH - angle, baseH + angle];
|
||||
}
|
||||
|
||||
type Layer =
|
||||
'outer' | 'spines' | 'vitiligo1' |
|
||||
'stripes' | 'cuffs' |
|
||||
'fins1' | 'fins2' | 'fins3' | 'vitiligo4' |
|
||||
'belly1' | 'vitiligo3' | 'belly2' | 'vitiligo2' |
|
||||
'eyes' | 'masks' | 'claws' | 'lines';
|
||||
|
||||
type Colours = { [l in Layer]: Oklch };
|
||||
|
||||
function colours(): Colours {
|
||||
let cols: Partial<Colours> = {};
|
||||
|
||||
cols.outer = baseOklch('dark'); // [todo]
|
||||
cols.spines = mkSpines(cols.outer);
|
||||
cols.vitiligo1 = mkVitiligo(cols.outer);
|
||||
|
||||
cols.stripes = mkStripes();
|
||||
cols.cuffs = mkCuffs(cols.stripes);
|
||||
|
||||
// fins, belly
|
||||
const whichBody = rand();
|
||||
if (whichBody > 0.85) {
|
||||
// triad
|
||||
const hs = triad(cols.outer.h);
|
||||
fins(hs[0]); belly(hs[1]);
|
||||
} else if (whichBody > 0.4) {
|
||||
// fins like belly
|
||||
const [f, b] = complementary(cols.outer.h, 2);
|
||||
fins(f!); belly(b!);
|
||||
} else {
|
||||
// fins like outer
|
||||
fins(analogous(cols.outer.h, 3)[2]!);
|
||||
belly(complementary(cols.outer.h, 3)[2]!);
|
||||
}
|
||||
|
||||
cols.eyes = {
|
||||
l: baseLuma('light'),
|
||||
c: randBetween(0.28, MAXC_LIGHT),
|
||||
h: oneOf(analogous, complementary)(cols.outer.h, 3)[2]!
|
||||
};
|
||||
|
||||
cols.masks = {
|
||||
l: randBetween(0.8, MAXL),
|
||||
c: randBetween(0.01, 0.06),
|
||||
h: analogous(oneOf(cols.outer, cols.belly1, cols.fins1)!.h, 3)[2]!
|
||||
};
|
||||
cols.claws = {
|
||||
l: min(MAXL, cols.masks!.l + randBetween(0.1, -0.1)),
|
||||
c: randBetween(0.01, 0.06),
|
||||
h: analogous(cols.masks!.h, 3)[2]!
|
||||
};
|
||||
|
||||
cols.lines = {
|
||||
l: randBetween(0.01, 0.06),
|
||||
c: baseChroma(0),
|
||||
h: analogous(cols.outer!.h, 3)[2]!
|
||||
}
|
||||
|
||||
return cols as Colours;
|
||||
|
||||
|
||||
function fins(h: number) {
|
||||
const [fin1Hue, fin2Hue, fin3Hue] = analogous(h, 3);
|
||||
const d = direction();
|
||||
cols.fins1 = doDirection(cols.outer!, fin1Hue!, d);
|
||||
cols.fins2 = doDirection(cols.fins1, fin2Hue!, d);
|
||||
cols.fins3 = doDirection(cols.fins2, fin3Hue!, d);
|
||||
cols.vitiligo4 = mkVitiligo(cols.fins1);
|
||||
}
|
||||
|
||||
function belly(h: number) {
|
||||
const [belly1Hue, belly2Hue] = analogous(h, 2);
|
||||
cols.belly1 = {
|
||||
l: randBetween(0.7, MAXL),
|
||||
c: baseChroma(1),
|
||||
h: belly1Hue!
|
||||
};
|
||||
cols.belly2 = {
|
||||
l: min(MAXL, cols.belly1!.l * 1.1),
|
||||
c: cols.belly1!.c * 0.9,
|
||||
h: belly2Hue!
|
||||
};
|
||||
cols.vitiligo3 = mkVitiligo(cols.belly1); // oops sorry
|
||||
cols.vitiligo2 = mkVitiligo(cols.belly2);
|
||||
}
|
||||
|
||||
type LFun = (l: number) => number;
|
||||
type CFun = (l: number, c: number) => number;
|
||||
function direction(): [LFun, CFun] {
|
||||
return oneOf([lightFor, dullFor], [darkFor, brightFor]);
|
||||
}
|
||||
function doDirection(col: Oklch, h: number, [ll, cc]: [LFun, CFun]) {
|
||||
return { l: ll(col.l), c: cc(col.l, col.c), h };
|
||||
}
|
||||
}
|
||||
|
||||
function mkVitiligo(outer: Oklch): Oklch {
|
||||
return {
|
||||
l: randBetween(max(outer.l, 0.8), MAXL),
|
||||
c: randBetween(min(outer.c, 0.1), MINC_LIGHT),
|
||||
h: randBetween(outer.h + 20, outer.h - 20)
|
||||
};
|
||||
}
|
||||
|
||||
function mkSpines(outer: Oklch): Oklch {
|
||||
return {
|
||||
l: outer.l * 0.8, c: outer.c * 1.1,
|
||||
h: randBetween(outer.h + 12, outer.h - 12)
|
||||
};
|
||||
}
|
||||
|
||||
function mkStripes(): Oklch {
|
||||
return {
|
||||
l: randBetween(0.8, MAXL),
|
||||
c: randBetween(MINC_LIGHT, MAXC_LIGHT),
|
||||
h: rand() * 360
|
||||
};
|
||||
}
|
||||
|
||||
function mkCuffs(sock: Oklch): Oklch {
|
||||
return {
|
||||
l: sock.l * 0.7,
|
||||
c: randBetween(sock.c, MAXC_LIGHT),
|
||||
h: randBetween(sock.h + 8, sock.h - 8)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function setColours(cols: Colours) {
|
||||
for (const k in cols) {
|
||||
const c = cols[k as keyof Colours];
|
||||
for (const elem of Array.from(document.getElementsByClassName(k))) {
|
||||
(elem as HTMLElement).style.background = `oklch(${c.l} ${c.c} ${c.h})`;
|
||||
}
|
||||
}
|
||||
document.documentElement.style.setProperty('--hue', `${cols.outer.h}deg`);
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const reroll = document.getElementById('reroll')!;
|
||||
const swap = document.getElementById('swap')!;
|
||||
const pic = document.getElementById('pic')!;
|
||||
|
||||
reroll.addEventListener('click', doReroll);
|
||||
swap.addEventListener('click', doSwap);
|
||||
|
||||
doReroll();
|
||||
setTimeout(setTransition);
|
||||
|
||||
function doReroll() { setColours(colours()); }
|
||||
function doSwap() { pic.classList.toggle('back'); }
|
||||
function setTransition() {
|
||||
document.documentElement.style.setProperty('--transition',
|
||||
'background 0.4s ease-in-out, color 0.4s ease-in-out');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export {}
|
BIN
rainbow-quox/front/belly1.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/belly1.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/belly2.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/belly2.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/claws.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/claws.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/cuffs.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/cuffs.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/eyes.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/eyes.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/fins1.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/fins1.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/fins2.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/fins2.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/fins3.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/fins3.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/lines.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/lines.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/masks.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/masks.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/outer.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/outer.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/spines.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/spines.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/static.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/static.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/stripes.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/stripes.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo1.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo1.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo2.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo2.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo3.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo3.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo4.webp
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo4.webp
(Stored with Git LFS)
Normal file
Binary file not shown.
63
rainbow-quox/index.html
Normal file
63
rainbow-quox/index.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!doctype html>
|
||||
|
||||
<title>rainbow quox</title>
|
||||
|
||||
<link rel=stylesheet href=style.css>
|
||||
<script src=colour.js type=module></script>
|
||||
|
||||
<div id=pic-holder>
|
||||
<div id=pic>
|
||||
<div id=front>
|
||||
<div class=static></div>
|
||||
<div class=spines></div>
|
||||
<div class=stripes></div>
|
||||
<div class=cuffs></div>
|
||||
<div class=outer></div>
|
||||
<div class=fins1></div>
|
||||
<div class=fins2></div>
|
||||
<div class=fins3></div>
|
||||
<div class=belly1></div>
|
||||
<div class=belly2></div>
|
||||
<div class=eyes></div>
|
||||
<div class=masks></div>
|
||||
<div class=claws></div>
|
||||
<div class=vitiligo1></div>
|
||||
<div class=vitiligo2></div>
|
||||
<div class=vitiligo3></div>
|
||||
<div class=vitiligo4></div>
|
||||
<div class=eye-shine></div>
|
||||
<div class=lines></div>
|
||||
</div>
|
||||
|
||||
<div id=back>
|
||||
<div class=static></div>
|
||||
<div class=spines></div>
|
||||
<div class=stripes></div>
|
||||
<div class=cuffs></div>
|
||||
<div class=outer></div>
|
||||
<div class=fins1></div>
|
||||
<div class=fins2></div>
|
||||
<div class=fins3></div>
|
||||
<div class=belly1></div>
|
||||
<div class=belly2></div>
|
||||
<div class=eyes></div>
|
||||
<div class=masks></div>
|
||||
<div class=claws></div>
|
||||
<div class=vitiligo1></div>
|
||||
<div class=vitiligo2></div>
|
||||
<div class=vitiligo3></div>
|
||||
<div class=vitiligo4></div>
|
||||
<div class=eye-shine></div>
|
||||
<div class=lines></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<menu id=buttons>
|
||||
<button id=reroll>new quox</button>
|
||||
<button id=swap>swap view</button>
|
||||
</menu>
|
||||
|
||||
<nav>
|
||||
<a href=/>back</a>
|
||||
</nav>
|
BIN
rainbow-quox/kra/back.kra
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/kra/back.kra
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/kra/compl1.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/kra/compl1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/kra/compl2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/kra/compl2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/kra/front.kra
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/kra/front.kra
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/kra/triad.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/kra/triad.png
(Stored with Git LFS)
Normal file
Binary file not shown.
164
rainbow-quox/style.css
Normal file
164
rainbow-quox/style.css
Normal file
|
@ -0,0 +1,164 @@
|
|||
@import url(/fonts/muller/muller.css);
|
||||
|
||||
@property --transition {
|
||||
syntax: "*";
|
||||
inherits: true;
|
||||
initial-value: none;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* { transition: none; }
|
||||
}
|
||||
|
||||
:root {
|
||||
--hue: 300deg;
|
||||
min-height: 100vh; display: flex;
|
||||
align-items: center; justify-content: center;
|
||||
|
||||
--font: Muller, sans-serif;
|
||||
font-family: var(--font);
|
||||
|
||||
color-scheme: light dark;
|
||||
background:
|
||||
light-dark(oklch(0.9 0.08 var(--hue)),
|
||||
oklch(0.3 0.12 var(--hue)));
|
||||
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#pic {
|
||||
position: relative;
|
||||
width: min(1000px, 75vw);
|
||||
margin: auto;
|
||||
aspect-ratio: 2000/1312;
|
||||
}
|
||||
#pic div {
|
||||
position: absolute; inset: 0;
|
||||
mask-size: contain; mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
#front, #back {
|
||||
transition: all 0.45s cubic-bezier(.23,-0.03,.68,1.11);
|
||||
}
|
||||
|
||||
.back > #front { translate: 125vw; }
|
||||
:not(.back) > #back { translate: -125vw; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
#front, #back { transition: none; }
|
||||
|
||||
.back > #front { translate: none; rotate: none; display: none; }
|
||||
:not(.back) > #back { translate: none; rotate: none; display: none; }
|
||||
}
|
||||
|
||||
|
||||
#front .static { background: url(front/static.webp) 0 0 / contain; }
|
||||
#back .static { background: url(back/static.webp) 0 0 / contain; }
|
||||
|
||||
.spines { background: oklch(30.77% 0.1306 298.19); }
|
||||
#front .spines { mask-image: url(front/spines.webp); }
|
||||
#back .spines { mask-image: url(back/spines.webp); }
|
||||
|
||||
.stripes { background: oklch(88.2% 0.0613 209.07); }
|
||||
#front .stripes { mask-image: url(front/stripes.webp); }
|
||||
#back .stripes { mask-image: url(back/stripes.webp); }
|
||||
|
||||
.cuffs { background: oklch(72.74% 0.1008 225.69); }
|
||||
#front .cuffs { mask-image: url(front/cuffs.webp); }
|
||||
#back .cuffs { mask-image: url(back/cuffs.webp); }
|
||||
|
||||
.outer { background: oklch(38.37% 0.1437 306.27); }
|
||||
#front .outer { mask-image: url(front/outer.webp); }
|
||||
#back .outer { mask-image: url(back/outer.webp); }
|
||||
|
||||
.fins1 { background: oklch(85.06% 0.0961 81.4); }
|
||||
#front .fins1 { mask-image: url(front/fins1.webp); }
|
||||
#back .fins1 { mask-image: url(back/fins1.webp); }
|
||||
|
||||
.fins2 { background: oklch(79.59% 0.1208 73.56); }
|
||||
#front .fins2 { mask-image: url(front/fins2.webp); }
|
||||
#back .fins2 { mask-image: url(back/fins2.webp); }
|
||||
|
||||
.fins3 { background: oklch(74.11% 0.1268 64.62); }
|
||||
#front .fins3 { mask-image: url(front/fins3.webp); }
|
||||
#back .fins3 { mask-image: url(back/fins3.webp); }
|
||||
|
||||
.belly1 { background: oklch(87.26% 0.0699 80.94); }
|
||||
#front .belly1 { mask-image: url(front/belly1.webp); }
|
||||
#back .belly1 { mask-image: url(back/belly1.webp); }
|
||||
|
||||
.belly2 { background: oklch(76.92% 0.0954 58.36); }
|
||||
#front .belly2 { mask-image: url(front/belly2.webp); }
|
||||
#back .belly2 { mask-image: url(back/belly2.webp); }
|
||||
|
||||
.eyes { background: oklch(36.26% 0.1107 145.78); }
|
||||
#front .eyes { mask-image: url(front/eyes.webp); }
|
||||
#back .eyes { mask-image: url(back/eyes.webp); }
|
||||
|
||||
.masks { background: oklch(77.1% 0.0243 317.12); }
|
||||
#front .masks { mask-image: url(front/masks.webp); }
|
||||
#back .masks { mask-image: url(back/masks.webp); }
|
||||
|
||||
.claws { background: oklch(88.92% 0.0207 325.75); }
|
||||
#front .claws { mask-image: url(front/claws.webp); }
|
||||
#back .claws { mask-image: url(back/claws.webp); }
|
||||
|
||||
.vitiligo1 { background: oklch(79.4% 0.0588 309.27); }
|
||||
#front .vitiligo1 { mask-image: url(front/vitiligo1.webp); }
|
||||
#back .vitiligo1 { mask-image: url(back/vitiligo1.webp); }
|
||||
|
||||
.vitiligo2 { background: oklch(93.14% 0.0331 83.71); }
|
||||
#front .vitiligo2 { mask-image: url(front/vitiligo2.webp); }
|
||||
#back .vitiligo2 { mask-image: url(back/vitiligo2.webp); }
|
||||
|
||||
.vitiligo3 { background: oklch(95.7% 0.0296 94.35); }
|
||||
#front .vitiligo3 { mask-image: url(front/vitiligo3.webp); }
|
||||
#back .vitiligo3 { mask-image: url(back/vitiligo3.webp); }
|
||||
|
||||
.vitiligo4 { background: oklch(95.7% 0.0296 94.35); }
|
||||
#front .vitiligo4 { mask-image: url(front/vitiligo4.webp); }
|
||||
#back .vitiligo4 { mask-image: url(back/vitiligo4.webp); }
|
||||
|
||||
.lines { background: oklch(21.96% 0.0661 296.36); }
|
||||
#front .lines { mask-image: url(front/lines.webp); }
|
||||
#back .lines { mask-image: url(back/lines.webp); }
|
||||
|
||||
.eye-shine { mask: none; mix-blend-mode: luminosity; }
|
||||
#front .eye-shine { background: url(front/eyes.webp) 0 0 / contain; }
|
||||
#back .eye-shine { background: url(back/eyes.webp) 0 0 / contain; }
|
||||
|
||||
|
||||
#buttons {
|
||||
margin-top: 3rem;
|
||||
display: flex; gap: 20px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
button {
|
||||
font: 700 25pt var(--font);
|
||||
flex: 30%;
|
||||
background: oklch(0.5 0.2 var(--hue));
|
||||
color: oklch(0.95 0.075 calc(180deg + var(--hue)));
|
||||
border: 3px solid oklch(0.2 0.05 var(--hue));
|
||||
padding: 0.2em 0.5em;
|
||||
filter: drop-shadow(0 0 10px oklch(0.4 0.2 var(--hue) / 0.45));
|
||||
}
|
||||
|
||||
nav {
|
||||
position: absolute;
|
||||
bottom: 15px; left: 22px;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: light-dark(oklch(0.4 0.15 calc(180deg + var(--hue))),
|
||||
oklch(0.9 0.19 calc(180deg + var(--hue))));
|
||||
text-decoration: 3px solid underline;
|
||||
text-decoration-color:
|
||||
oklch(0.6 0.1 calc(180deg + var(--hue)));
|
||||
}
|
Loading…
Add table
Reference in a new issue