rainbow quox on canvas. mostly working
This commit is contained in:
parent
60201e27aa
commit
d16ea49d62
79 changed files with 553 additions and 286 deletions
6
Makefile
6
Makefile
|
@ -5,8 +5,8 @@ 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 \
|
||||
$(wildcard rainbow-quox/front/*) $(wildcard rainbow-quox/back/*)
|
||||
SCRIPTS = $(patsubst %.ts,%.js,$(wildcard script/*.ts)) rainbow-quox/colour.js
|
||||
$(wildcard rainbow-quox/front/*.png) $(wildcard rainbow-quox/back/*.png)
|
||||
SCRIPTS = $(patsubst %.ts,%.js,$(wildcard script/*.ts rainbow-quox/*.ts))
|
||||
MISC = $(shell find .well-known -type f)
|
||||
ALL = $(CSS) $(PAGES) $(MEDIA) $(SCRIPTS) $(MISC)
|
||||
|
||||
|
@ -56,7 +56,7 @@ $(BUILDDIR)/%_dim.png: %.png
|
|||
|
||||
$(BUILDDIR)/%.js: %.ts
|
||||
tsc --strict --noUncheckedIndexedAccess --noEmitOnError \
|
||||
--lib dom,es2021 --target es2015 \
|
||||
--lib dom,es2023 --target es2015 \
|
||||
--outDir $(dir $@) $^
|
||||
|
||||
|
||||
|
|
BIN
rainbow-quox/back/belly1.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/belly1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/belly1.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/belly1.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/belly2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/belly2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/belly2.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/belly2.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/claws.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/claws.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/claws.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/claws.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/cuffs.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/cuffs.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/cuffs.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/cuffs.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/eyes.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/eyes.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/eyes.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/eyes.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/fins1.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/fins1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/fins1.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/fins1.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/fins2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/fins2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/fins2.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/fins2.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/fins3.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/fins3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/fins3.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/fins3.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/lines.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/lines.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/lines.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/lines.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/masks.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/masks.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/masks.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/masks.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/outer.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/outer.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/outer.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/outer.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/spines.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/spines.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/spines.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/spines.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/static.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/static.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/static.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/static.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/stripes.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/stripes.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/stripes.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/stripes.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/vitiligo1.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo1.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/vitiligo1.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/vitiligo2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo2.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/vitiligo2.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/vitiligo3.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo3.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/vitiligo3.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/back/vitiligo4.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/back/vitiligo4.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/back/vitiligo4.webp
(Stored with Git LFS)
BIN
rainbow-quox/back/vitiligo4.webp
(Stored with Git LFS)
Binary file not shown.
304
rainbow-quox/canvas.ts
Normal file
304
rainbow-quox/canvas.ts
Normal file
|
@ -0,0 +1,304 @@
|
|||
import * as Color from './color.js';
|
||||
|
||||
export const WIDTH = 1000;
|
||||
export const HEIGHT = 673;
|
||||
|
||||
|
||||
export type Layer = 'static' | 'eyeshine' | Color.Layer;
|
||||
|
||||
// in compositing order
|
||||
export const allLayers: Layer[] =
|
||||
['static', 'outer', 'spines', 'stripes', 'cuffs', 'fins1', 'fins2', 'fins3',
|
||||
'belly1', 'belly2', 'masks', 'claws', 'vitiligo1', 'vitiligo2', 'vitiligo3',
|
||||
'vitiligo4', 'eyes', 'eyeshine', 'lines'];
|
||||
|
||||
export type Image = ImageData;
|
||||
export type Images = Record<Layer, Image>;
|
||||
|
||||
export type ComposedImages = Images & {comp?: ImageData};
|
||||
|
||||
export type Side = 'front' | 'back';
|
||||
|
||||
export function flip(s: Side): Side {
|
||||
return s == 'front' ? 'back' : 'front';
|
||||
}
|
||||
|
||||
|
||||
let buffer = new OffscreenCanvas(WIDTH, HEIGHT);
|
||||
let bufferCtx = buffer.getContext('2d')!;
|
||||
|
||||
type Positions = Record<Layer, [number, number]>;
|
||||
|
||||
const FRONT_POS: Positions = {
|
||||
belly1: [187, 105],
|
||||
belly2: [186, 91],
|
||||
claws: [3, 168],
|
||||
cuffs: [42, 160],
|
||||
eyes: [223, 52],
|
||||
eyeshine: [223, 52],
|
||||
fins1: [381, 31],
|
||||
fins2: [387, 35],
|
||||
fins3: [495, 140],
|
||||
lines: [1, 0],
|
||||
masks: [173, 3],
|
||||
outer: [28, 43],
|
||||
spines: [372, 23],
|
||||
static: [50, 52],
|
||||
stripes: [50, 168],
|
||||
vitiligo1: [34, 23],
|
||||
vitiligo2: [198, 92],
|
||||
vitiligo3: [214, 312],
|
||||
vitiligo4: [647, 71],
|
||||
};
|
||||
|
||||
const BACK_POS: Positions = {
|
||||
belly1: [39, 67],
|
||||
belly2: [92, 95],
|
||||
claws: [191, 334],
|
||||
cuffs: [221, 215],
|
||||
eyes: [685, 42],
|
||||
eyeshine: [685, 42],
|
||||
fins1: [227, 60],
|
||||
fins2: [226, 61],
|
||||
fins3: [229, 195],
|
||||
lines: [0, 0],
|
||||
masks: [643, 1],
|
||||
outer: [2, 22],
|
||||
spines: [337, 50],
|
||||
static: [219, 41],
|
||||
stripes: [219, 221],
|
||||
vitiligo1: [4, 22],
|
||||
vitiligo2: [46, 48],
|
||||
vitiligo3: [101, 134],
|
||||
vitiligo4: [221, 56],
|
||||
};
|
||||
|
||||
|
||||
type Rgb = [number, number, number];
|
||||
type Rgbs = Record<Color.Layer, Rgb>;
|
||||
|
||||
function toRgb(col: Color.Oklch): Rgb {
|
||||
// :)
|
||||
const prev = bufferCtx.getImageData(0, 0, 1, 1);
|
||||
|
||||
bufferCtx.save();
|
||||
bufferCtx.fillStyle = Color.oklch(col);
|
||||
bufferCtx.fillRect(0, 0, 1, 1);
|
||||
bufferCtx.restore();
|
||||
|
||||
const rgb = bufferCtx.getImageData(0, 0, 1, 1).data;
|
||||
bufferCtx.putImageData(prev, 0, 0);
|
||||
|
||||
return [rgb[0]!, rgb[1]!, rgb[2]!];
|
||||
}
|
||||
|
||||
function toRgbs(col: Color.Colors): Rgbs {
|
||||
return Color.makeColorInfo(l => toRgb(col[l]));
|
||||
}
|
||||
|
||||
|
||||
function setImageDataRgb([r, g, b]: Rgb, img: Image): void {
|
||||
let data = img.data;
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
data[i] = r; data[i+1] = g; data[i+2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function wait(img: HTMLImageElement): Promise<HTMLImageElement> {
|
||||
if (img.complete) {
|
||||
return new Promise((r, _) => r(img));
|
||||
} else {
|
||||
return new Promise((r, _) => img.addEventListener('load', () => r(img)));
|
||||
}
|
||||
}
|
||||
|
||||
async function load(side: Side, layer: Layer): Promise<Image> {
|
||||
if (layer == 'eyeshine') layer = 'eyes';
|
||||
let img = new Image; img.src = `./${side}/${layer}.png`;
|
||||
let bmp = await createImageBitmap(await wait(img));
|
||||
bufferCtx.clearRect(0, 0, WIDTH, HEIGHT); // ?
|
||||
bufferCtx.drawImage(bmp, 0, 0);
|
||||
return bufferCtx.getImageData(0, 0, WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
async function loadSide(side: Side): Promise<ComposedImages> {
|
||||
const res: Partial<ComposedImages> = { };
|
||||
for (const l of allLayers) { res[l] = await load(side, l); }
|
||||
return res as ComposedImages;
|
||||
}
|
||||
|
||||
function setColors(cols: Rgbs, layers: ComposedImages): void {
|
||||
bufferCtx.save();
|
||||
|
||||
for (const l of allLayers) {
|
||||
if (l == 'static' || l == 'eyeshine') continue;
|
||||
setImageDataRgb(cols[l], layers[l]);
|
||||
}
|
||||
|
||||
delete layers.comp;
|
||||
|
||||
bufferCtx.restore();
|
||||
}
|
||||
|
||||
async function compose(layers: Images, pos: Positions): Promise<ImageData> {
|
||||
bufferCtx.save();
|
||||
bufferCtx.clearRect(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
for (const l of allLayers) {
|
||||
const [x, y] = pos[l];
|
||||
bufferCtx.globalCompositeOperation =
|
||||
l == 'eyeshine' ? 'luminosity' : 'source-over';
|
||||
bufferCtx.drawImage(await createImageBitmap(layers[l]), x, y);
|
||||
}
|
||||
|
||||
let res = bufferCtx.getImageData(0, 0, WIDTH, HEIGHT);
|
||||
bufferCtx.restore();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
async function redraw(ctx: CanvasRenderingContext2D,
|
||||
layers: ComposedImages, pos: Positions) {
|
||||
let data = layers.comp ??= await compose(layers, pos);
|
||||
ctx.putImageData(data, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
async function loadingMessage(): Promise<ImageBitmap> {
|
||||
bufferCtx.save();
|
||||
bufferCtx.clearRect(0, 0, WIDTH, HEIGHT);
|
||||
bufferCtx.font = 'bold 100px Muller, sans-serif';
|
||||
bufferCtx.textAlign = 'center';
|
||||
bufferCtx.fillText('loading layers…', WIDTH/2, HEIGHT/2);
|
||||
let res = createImageBitmap(buffer);
|
||||
bufferCtx.restore();
|
||||
return await res;
|
||||
}
|
||||
|
||||
|
||||
let pic: HTMLCanvasElement;
|
||||
let picCtx: CanvasRenderingContext2D;
|
||||
|
||||
let pic2: HTMLCanvasElement;
|
||||
let pic2Ctx: CanvasRenderingContext2D;
|
||||
|
||||
let fronts: Images;
|
||||
let backs: Images;
|
||||
|
||||
let side: Side = 'front';
|
||||
|
||||
function startAnim(name: string) {
|
||||
document.documentElement.dataset.running = name;
|
||||
}
|
||||
|
||||
function isRunning(): boolean {
|
||||
return !!document.documentElement.dataset.running;
|
||||
}
|
||||
|
||||
function finishAnim() {
|
||||
delete document.documentElement.dataset.running;
|
||||
}
|
||||
|
||||
function layers(): Images { return side == 'front' ? fronts : backs; }
|
||||
function pos(): Positions { return side == 'front' ? FRONT_POS : BACK_POS; }
|
||||
|
||||
|
||||
async function recolorOn(ctx: CanvasRenderingContext2D) {
|
||||
const cols = Color.colors();
|
||||
const rgbs = toRgbs(cols);
|
||||
setColors(rgbs, fronts);
|
||||
setColors(rgbs, backs);
|
||||
await redraw(ctx, layers(), pos());
|
||||
return cols.outer.h;
|
||||
}
|
||||
|
||||
function setBg(hue: number) {
|
||||
document.documentElement.style.setProperty('--hue', `${hue}`);
|
||||
}
|
||||
|
||||
|
||||
async function animateReroll(_e: Event, done: () => void) {
|
||||
const duration = 400;
|
||||
const hue = await recolorOn(pic2Ctx);
|
||||
pic2.style.animation = `${duration}ms ease fade-in`;
|
||||
setBg(hue);
|
||||
setTimeout(finish, duration);
|
||||
|
||||
async function finish() {
|
||||
await redraw(picCtx, layers(), pos()).then(() => {
|
||||
pic2.style.removeProperty('animation');
|
||||
pic2.style.removeProperty('opacity');
|
||||
done();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function animateSwap(_e: Event, done: () => void) {
|
||||
const duration = 1000;
|
||||
pic.style.animation = `${duration}ms ease swap`;
|
||||
setTimeout(swapImage, duration/2);
|
||||
setTimeout(finish, duration);
|
||||
|
||||
async function swapImage() {
|
||||
side = flip(side);
|
||||
await redraw(picCtx, layers(), pos());
|
||||
}
|
||||
|
||||
function finish() {
|
||||
pic.style.removeProperty('animation');
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
pic = document.getElementById('pic') as HTMLCanvasElement;
|
||||
picCtx = pic.getContext('2d')!;
|
||||
|
||||
pic2 = document.getElementById('pic2') as HTMLCanvasElement;
|
||||
pic2Ctx = pic2.getContext('2d')!;
|
||||
|
||||
picCtx.drawImage(await loadingMessage(), 0, 0);
|
||||
|
||||
fronts = await loadSide('front');
|
||||
backs = await loadSide('back');
|
||||
side = 'front';
|
||||
|
||||
let hue = await recolorOn(picCtx);
|
||||
setBg(hue);
|
||||
await redraw(picCtx, layers(), pos());
|
||||
|
||||
const reroll = document.getElementById('reroll')!;
|
||||
const swap = document.getElementById('swap')!;
|
||||
|
||||
addListeners();
|
||||
|
||||
function addListeners() {
|
||||
reroll.addEventListener('click', handleReroll);
|
||||
swap.addEventListener('click', handleSwap);
|
||||
}
|
||||
|
||||
function removeListeners() {
|
||||
reroll.removeEventListener('click', handleReroll);
|
||||
swap.removeEventListener('click', handleSwap);
|
||||
}
|
||||
|
||||
function handleReroll(e: Event) { wrap(reroll, animateReroll, 'reroll', e); }
|
||||
function handleSwap(e: Event) { wrap(swap, animateSwap, 'swap', e); }
|
||||
|
||||
type HandlerWithFinish = (e: Event, finish: () => void) => void;
|
||||
|
||||
function wrap(elem: Element, f: HandlerWithFinish,
|
||||
name: string, e: Event) {
|
||||
if (elem != e.target) return;
|
||||
e.stopPropagation();
|
||||
if (isRunning()) return;
|
||||
removeListeners();
|
||||
startAnim(name);
|
||||
f(e, () => { finishAnim(); addListeners(); });
|
||||
}
|
||||
});
|
||||
|
||||
export { load, loadSide };
|
|
@ -3,7 +3,11 @@ const rand: () => number = Math.random; // [todo]
|
|||
const max = Math.max;
|
||||
const min = Math.min;
|
||||
|
||||
type Oklch = { l: number, c: number, h: number };
|
||||
export type Oklch = { l: number, c: number, h: number };
|
||||
|
||||
export function oklch(col: Oklch, alpha: number = 1): string {
|
||||
return `oklch(${col.l} ${col.c} ${col.h} / ${alpha})`;
|
||||
}
|
||||
|
||||
type LD = 'light' | 'dark';
|
||||
|
||||
|
@ -17,17 +21,17 @@ const MAXC_LIGHT = 0.1;
|
|||
const MINC_DARK = 0.12;
|
||||
const MAXC_DARK = 0.175;
|
||||
|
||||
// max spread for a sequence of analogous colours. unless that would put them
|
||||
// max spread for a sequence of analogous colors. unless that would put them
|
||||
// too close together
|
||||
const MAXH_WIDTH = 80;
|
||||
|
||||
// minimum distance between adjacent analogous colours
|
||||
// minimum distance between adjacent analogous colors
|
||||
const MINH_SEP = 5;
|
||||
|
||||
// size of the wedge a "complementary" colour can be in
|
||||
// size of the wedge a "complementary" color can be in
|
||||
const MAXH_COMPL = 40;
|
||||
|
||||
// size of the wedge a "triadic" colour can be in
|
||||
// size of the wedge a "triadic" color can be in
|
||||
const MAXH_TRIAD = 25;
|
||||
|
||||
function randBetween(x: number, y: number): number {
|
||||
|
@ -113,24 +117,37 @@ function triad(baseH: number): [number, number] {
|
|||
return [baseH - angle, baseH + angle];
|
||||
}
|
||||
|
||||
type SchemeType = 'triad' | 'fin-belly' | 'fin-body';
|
||||
export type SchemeType = 'triad' | 'fin-belly' | 'fin-body';
|
||||
|
||||
type OuterLayer = 'outer' | 'spines' | 'vitiligo1';
|
||||
type SockLayer = 'stripes' | 'cuffs';
|
||||
type FinLayer = 'fins1' | 'fins2' | 'fins3' | 'vitiligo4';
|
||||
type BellyLayer = 'belly1' | 'vitiligo3' | 'belly2' | 'vitiligo2';
|
||||
type MiscLayer = 'eyes' | 'masks' | 'claws' | 'lines';
|
||||
type Layer = OuterLayer | SockLayer | FinLayer | BellyLayer | MiscLayer;
|
||||
export type OuterLayer = 'outer' | 'spines' | 'vitiligo1';
|
||||
export type SockLayer = 'stripes' | 'cuffs';
|
||||
export type FinLayer = 'fins1' | 'fins2' | 'fins3' | 'vitiligo4';
|
||||
export type BellyLayer = 'belly1' | 'vitiligo3' | 'belly2' | 'vitiligo2';
|
||||
export type MiscLayer = 'eyes' | 'masks' | 'claws' | 'lines';
|
||||
export type Layer =
|
||||
OuterLayer | SockLayer | FinLayer | BellyLayer | MiscLayer;
|
||||
|
||||
type ColsOf<A extends string> = Record<A, Oklch>;
|
||||
type OuterCols = ColsOf<OuterLayer>;
|
||||
type SockCols = ColsOf<SockLayer>;
|
||||
type FinCols = ColsOf<FinLayer>;
|
||||
type BellyCols = ColsOf<BellyLayer>;
|
||||
type MiscCols = ColsOf<MiscLayer>;
|
||||
type Colours = ColsOf<Layer> & {type: SchemeType};
|
||||
export type ColsOf<A extends string> = Record<A, Oklch>;
|
||||
export type OuterCols = ColsOf<OuterLayer>;
|
||||
export type SockCols = ColsOf<SockLayer>;
|
||||
export type FinCols = ColsOf<FinLayer>;
|
||||
export type BellyCols = ColsOf<BellyLayer>;
|
||||
export type MiscCols = ColsOf<MiscLayer>;
|
||||
export type Colors = ColsOf<Layer>;
|
||||
|
||||
function colours(): Colours {
|
||||
export type Scheme = Colors & {type: SchemeType};
|
||||
|
||||
export const allLayers: Layer[] =
|
||||
['outer', 'spines', 'stripes', 'cuffs', 'fins1', 'fins2', 'fins3',
|
||||
'belly1', 'belly2', 'masks', 'claws', 'vitiligo1', 'vitiligo2', 'vitiligo3',
|
||||
'vitiligo4', 'eyes', 'lines'];
|
||||
|
||||
export function makeColorInfo<A>(f: (l: Layer) => A): Record<Layer, A> {
|
||||
return Object.fromEntries(allLayers.map(l => [l, f(l)])) as Record<Layer, A>;
|
||||
}
|
||||
|
||||
|
||||
export function colors(): Scheme {
|
||||
const outer = baseOklch('dark');
|
||||
let outerCols: OuterCols =
|
||||
{ outer, spines: mkSpines(outer), vitiligo1: mkVitiligo(outer) };
|
||||
|
@ -243,44 +260,9 @@ function merge({ outer, spines, vitiligo1 }: OuterCols,
|
|||
{ fins1, fins2, fins3, vitiligo4 }: FinCols,
|
||||
{ belly1, vitiligo3, belly2, vitiligo2 }: BellyCols,
|
||||
{ eyes, masks, claws, lines }: MiscCols,
|
||||
type: SchemeType): Colours {
|
||||
type: SchemeType): Scheme {
|
||||
return {
|
||||
outer, spines, vitiligo1, stripes, cuffs, fins1, fins2, fins3, vitiligo4,
|
||||
belly1, vitiligo3, belly2, vitiligo2, eyes, masks, claws, lines, type
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function setColours(cols: Colours) {
|
||||
for (const k in cols) {
|
||||
if (k == 'type') continue;
|
||||
const c = cols[k as Exclude<keyof Colours, 'type'>];
|
||||
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}`);
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.getElementById('reroll')?.addEventListener('click', doReroll);
|
||||
document.getElementById('swap')?.addEventListener('click', doSwap);
|
||||
|
||||
doReroll();
|
||||
setTimeout(setTransition);
|
||||
|
||||
function doReroll() { setColours(colours()); }
|
||||
function doSwap() {
|
||||
document.getElementById('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.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/belly1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/belly1.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/belly1.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/belly2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/belly2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/belly2.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/belly2.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/claws.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/claws.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/claws.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/claws.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/cuffs.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/cuffs.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/cuffs.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/cuffs.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/eyes.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/eyes.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/eyes.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/eyes.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/fins1.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/fins1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/fins1.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/fins1.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/fins2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/fins2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/fins2.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/fins2.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/fins3.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/fins3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/fins3.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/fins3.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/lines.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/lines.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/lines.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/lines.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/masks.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/masks.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/masks.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/masks.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/outer.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/outer.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/outer.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/outer.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/spines.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/spines.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/spines.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/spines.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/static.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/static.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/static.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/static.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/stripes.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/stripes.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/stripes.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/stripes.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/vitiligo1.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo1.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/vitiligo1.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/vitiligo2.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo2.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/vitiligo2.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/vitiligo3.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo3.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/vitiligo3.webp
(Stored with Git LFS)
Binary file not shown.
BIN
rainbow-quox/front/vitiligo4.png
(Stored with Git LFS)
Normal file
BIN
rainbow-quox/front/vitiligo4.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
rainbow-quox/front/vitiligo4.webp
(Stored with Git LFS)
BIN
rainbow-quox/front/vitiligo4.webp
(Stored with Git LFS)
Binary file not shown.
|
@ -1,64 +1,26 @@
|
|||
<!doctype html>
|
||||
<html lang=en>
|
||||
|
||||
<meta name=viewport content='width=device-width, initial-scale=0.5'>
|
||||
|
||||
<title>rainbow quox</title>
|
||||
|
||||
<link rel=stylesheet href=style.css>
|
||||
<script src=colour.js type=module></script>
|
||||
<script src=canvas.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>
|
||||
<canvas id=pic width=1000 height=673>
|
||||
if the canvas isn't working,
|
||||
the old version is <a href=old.html>here</a>
|
||||
</canvas>
|
||||
<canvas id=pic2 width=1000 height=673>
|
||||
</canvas>
|
||||
</div>
|
||||
|
||||
<menu id=buttons>
|
||||
<div id=buttons>
|
||||
<button id=reroll>new quox</button>
|
||||
<button id=swap>swap view</button>
|
||||
</menu>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<a href=/>back</a>
|
||||
|
|
BIN
rainbow-quox/kra/back.kra
(Stored with Git LFS)
BIN
rainbow-quox/kra/back.kra
(Stored with Git LFS)
Binary file not shown.
|
@ -6,15 +6,25 @@
|
|||
initial-value: none;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
transition: var(--transition);
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* { transition: none; }
|
||||
}
|
||||
|
||||
@keyframes swap {
|
||||
0% { transform: none; }
|
||||
49% { transform: translateX(-150vw); }
|
||||
50% { content-visibility: hidden; }
|
||||
51% { transform: translateX(150vw); content-visibility: visible; }
|
||||
100% { transform: none; }
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0 }
|
||||
to { opacity: 1 }
|
||||
}
|
||||
|
||||
:root {
|
||||
--hue: 300;
|
||||
--c-hue: calc(180 + var(--hue));
|
||||
|
@ -26,6 +36,7 @@
|
|||
|
||||
color-scheme: light dark;
|
||||
background: oklch(0.9 0.08 var(--hue));
|
||||
transition: background 0.4s ease;
|
||||
|
||||
width: 100vw;
|
||||
overflow-x: hidden;
|
||||
|
@ -35,107 +46,95 @@
|
|||
:root { background: oklch(0.3 0.12 var(--hue)); }
|
||||
}
|
||||
|
||||
#pic {
|
||||
position: relative;
|
||||
#pic-holder, #pic, #pic2 {
|
||||
width: min(1000px, 75vw);
|
||||
margin: auto;
|
||||
aspect-ratio: 2000/1312;
|
||||
aspect-ratio: 2000/1346;
|
||||
}
|
||||
#pic div {
|
||||
position: absolute; inset: 0;
|
||||
mask-size: contain; mask-repeat: no-repeat;
|
||||
|
||||
#pic-holder { position: relative; }
|
||||
#pic, #pic2 { position: absolute; inset: 0; }
|
||||
|
||||
#pic2 {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
#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; }
|
||||
#front .static { background: url(ufront/static.png) 0 0 / contain; }
|
||||
#back .static { background: url(uback/static.png) 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); }
|
||||
#front .spines { mask-image: url(ufront/spines.png); }
|
||||
#back .spines { mask-image: url(uback/spines.png); }
|
||||
|
||||
.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); }
|
||||
#front .stripes { mask-image: url(ufront/stripes.png); }
|
||||
#back .stripes { mask-image: url(uback/stripes.png); }
|
||||
|
||||
.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); }
|
||||
#front .cuffs { mask-image: url(ufront/cuffs.png); }
|
||||
#back .cuffs { mask-image: url(uback/cuffs.png); }
|
||||
|
||||
.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); }
|
||||
#front .outer { mask-image: url(ufront/outer.png); }
|
||||
#back .outer { mask-image: url(uback/outer.png); }
|
||||
|
||||
.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); }
|
||||
#front .fins1 { mask-image: url(ufront/fins1.png); }
|
||||
#back .fins1 { mask-image: url(uback/fins1.png); }
|
||||
|
||||
.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); }
|
||||
#front .fins2 { mask-image: url(ufront/fins2.png); }
|
||||
#back .fins2 { mask-image: url(uback/fins2.png); }
|
||||
|
||||
.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); }
|
||||
#front .fins3 { mask-image: url(ufront/fins3.png); }
|
||||
#back .fins3 { mask-image: url(uback/fins3.png); }
|
||||
|
||||
.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); }
|
||||
#front .belly1 { mask-image: url(ufront/belly1.png); }
|
||||
#back .belly1 { mask-image: url(uback/belly1.png); }
|
||||
|
||||
.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); }
|
||||
#front .belly2 { mask-image: url(ufront/belly2.png); }
|
||||
#back .belly2 { mask-image: url(uback/belly2.png); }
|
||||
|
||||
.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); }
|
||||
#front .eyes { mask-image: url(ufront/eyes.png); }
|
||||
#back .eyes { mask-image: url(uback/eyes.png); }
|
||||
|
||||
.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); }
|
||||
#front .masks { mask-image: url(ufront/masks.png); }
|
||||
#back .masks { mask-image: url(uback/masks.png); }
|
||||
|
||||
.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); }
|
||||
#front .claws { mask-image: url(ufront/claws.png); }
|
||||
#back .claws { mask-image: url(uback/claws.png); }
|
||||
|
||||
.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); }
|
||||
#front .vitiligo1 { mask-image: url(ufront/vitiligo1.png); }
|
||||
#back .vitiligo1 { mask-image: url(uback/vitiligo1.png); }
|
||||
|
||||
.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); }
|
||||
#front .vitiligo2 { mask-image: url(ufront/vitiligo2.png); }
|
||||
#back .vitiligo2 { mask-image: url(uback/vitiligo2.png); }
|
||||
|
||||
.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); }
|
||||
#front .vitiligo3 { mask-image: url(ufront/vitiligo3.png); }
|
||||
#back .vitiligo3 { mask-image: url(uback/vitiligo3.png); }
|
||||
|
||||
.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); }
|
||||
#front .vitiligo4 { mask-image: url(ufront/vitiligo4.png); }
|
||||
#back .vitiligo4 { mask-image: url(uback/vitiligo4.png); }
|
||||
|
||||
.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); }
|
||||
#front .lines { mask-image: url(ufront/lines.png); }
|
||||
#back .lines { mask-image: url(uback/lines.png); }
|
||||
|
||||
.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; }
|
||||
#front .eye-shine { background: url(ufront/eyes.png) 0 0 / contain; }
|
||||
#back .eye-shine { background: url(uback/eyes.png) 0 0 / contain; }
|
||||
|
||||
|
||||
#buttons {
|
||||
|
@ -145,13 +144,28 @@
|
|||
}
|
||||
|
||||
button {
|
||||
--fg: var(--c-hue);
|
||||
--bg: var(--hue);
|
||||
font: 700 25pt var(--font);
|
||||
flex: 30%;
|
||||
background: oklch(0.5 0.2 var(--hue));
|
||||
color: oklch(0.95 0.075 var(--c-hue));
|
||||
border: 3px solid oklch(0.2 0.05 var(--hue));
|
||||
background: oklch(0.5 0.2 var(--bg));
|
||||
color: oklch(0.95 0.075 var(--fg));
|
||||
border: 3px solid oklch(0.2 0.05 var(--bg));
|
||||
padding: 0.2em 0.5em;
|
||||
filter: drop-shadow(0 0 10px oklch(0.4 0.2 var(--hue) / 0.45));
|
||||
box-shadow: 6px 6px 2px oklch(0.4 0.2 var(--bg) / 0.45);
|
||||
transition:
|
||||
color 0.4s ease,
|
||||
background 0.4s ease,
|
||||
border 0.4s ease,
|
||||
translate 0.025s ease-in,
|
||||
box-shadow 0.025s ease-in;
|
||||
|
||||
:root:not([data-running]) &:active,
|
||||
[data-running=swap] &#swap,
|
||||
[data-running=reroll] &#reroll {
|
||||
translate: 6px 6px;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
|
|
|
@ -19,7 +19,12 @@ html {
|
|||
color: black;
|
||||
|
||||
--gradient:
|
||||
linear-gradient(120deg, #fae58f, #fab6ba, #d1aeff, #89d6ff, #43f3ae);
|
||||
linear-gradient(120deg in oklch,
|
||||
oklch(93% 27.1% 96deg),
|
||||
oklch(84.03% 22% 15deg),
|
||||
oklch(80% 29.3% 303deg),
|
||||
oklch(84% 23% 233deg),
|
||||
oklch(89% 25% 161deg));
|
||||
--shadow-hsl: 330deg 40% 40%;
|
||||
--base-background: var(--gradient) fixed;
|
||||
background: var(--base-background);
|
||||
|
@ -251,7 +256,7 @@ strong { font-weight: 700; }
|
|||
|
||||
|
||||
#activities, #activities ::selection {
|
||||
--hue: 70deg;
|
||||
--hue: 60deg;
|
||||
--bg-angle: -60deg;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue