mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-19 14:24:47 -07:00
219 lines
5.1 KiB
CSS
219 lines
5.1 KiB
CSS
@property --pulse-mix {
|
|
syntax: "<number>";
|
|
inherits: true;
|
|
initial-value: 0;
|
|
}
|
|
|
|
:root {
|
|
--cube-size: 4.5rem;
|
|
--iso-scale: calc(sqrt(3) / 2);
|
|
--cube-empty-alpha: 0.4;
|
|
--face-step: 0.033;
|
|
}
|
|
|
|
.cube {
|
|
--cube-width: calc(var(--cube-size) * 2 * var(--iso-scale));
|
|
--cube-height: calc(var(--cube-size) * 2);
|
|
|
|
--cube-face-base: var(--border-color);
|
|
--face-top: light-dark(
|
|
var(--cube-face-base),
|
|
oklch(from var(--cube-face-base) calc(l + var(--face-step) * 2) c h)
|
|
);
|
|
--face-right: light-dark(
|
|
oklch(from var(--cube-face-base) calc(l - var(--face-step) * 2) c h),
|
|
var(--cube-face-base)
|
|
);
|
|
--face-left: light-dark(
|
|
oklch(from var(--cube-face-base) calc(l - var(--face-step)) c h),
|
|
oklch(from var(--cube-face-base) calc(l + var(--face-step)) c h)
|
|
);
|
|
--face-bottom: oklch(
|
|
from var(--cube-face-base) calc(l - var(--face-step) * 3) c h
|
|
);
|
|
|
|
--is-full: round(down, var(--fill), 1);
|
|
--is-empty: round(down, calc(1 - var(--fill)), 1);
|
|
|
|
flex-shrink: 0;
|
|
position: relative;
|
|
width: var(--cube-width);
|
|
height: var(--cube-height);
|
|
/* .cube can be an <a>; reset anchor styles that would clip the iso
|
|
silhouette or underline the empty link. */
|
|
overflow: visible;
|
|
text-decoration: none;
|
|
color: var(--color);
|
|
user-select: none;
|
|
pointer-events: none;
|
|
|
|
/* Hover/active styling is gated on the anchor tag: only <a> cubes
|
|
(confirmed blocks) react to pointer state. Plain <div> projected
|
|
previews stay visually inert. --face-color-base is resolved lazily,
|
|
so the orange override below feeds the face declarations too. */
|
|
&:is(a):hover,
|
|
&:is(a):active,
|
|
&.selected {
|
|
color: var(--background-color);
|
|
--face-color-base: var(--inv-border-color);
|
|
--face-top: var(--face-color-base);
|
|
--face-right: oklch(
|
|
from var(--face-color-base) calc(l - var(--face-step) * 2) c h
|
|
);
|
|
--face-left: oklch(
|
|
from var(--face-color-base) calc(l - var(--face-step)) c h
|
|
);
|
|
--face-bottom: oklch(
|
|
from var(--face-color-base) calc(l - var(--face-step) * 3) c h
|
|
);
|
|
}
|
|
|
|
&:is(a):active,
|
|
&.selected {
|
|
color: var(--black);
|
|
--face-color-base: var(--orange);
|
|
}
|
|
|
|
&.projected {
|
|
animation: cube-pulse 4s ease-in-out infinite;
|
|
--cube-face-base: color-mix(
|
|
in oklch,
|
|
var(--border-color),
|
|
var(--background-color) calc(var(--pulse-mix) * 100%)
|
|
);
|
|
}
|
|
|
|
/* visibility (not color:transparent) so child <img> hides too */
|
|
&.skeleton .face-text {
|
|
visibility: hidden;
|
|
}
|
|
|
|
.face {
|
|
position: absolute;
|
|
transform-origin: 0 0;
|
|
box-sizing: border-box;
|
|
width: var(--cube-size);
|
|
height: var(--cube-size);
|
|
transform: translateY(50%) var(--face-orient)
|
|
translate(
|
|
calc(var(--cube-size) * var(--face-x)),
|
|
calc(var(--cube-size) * var(--face-y))
|
|
)
|
|
scale(var(--face-scale-x, 1), var(--face-scale-y));
|
|
pointer-events: auto;
|
|
}
|
|
|
|
/* will-change on painted roles only so each gets its own compositor
|
|
layer for snappy hover/select repaints. */
|
|
.liquid,
|
|
.glass {
|
|
will-change: background-color;
|
|
}
|
|
.liquid {
|
|
background: var(--face-color);
|
|
opacity: calc(1 - var(--is-empty));
|
|
--face-scale-y: calc(var(--iso-scale) * var(--fill));
|
|
--face-stack-shift: calc(var(--iso-scale) * (1 - var(--fill)));
|
|
}
|
|
.glass {
|
|
background: oklch(from var(--face-color) l c h / var(--cube-empty-alpha));
|
|
--face-scale-y: calc(var(--iso-scale) * (1 - var(--fill)));
|
|
--face-stack-shift: 0;
|
|
}
|
|
|
|
.face-text {
|
|
--face-scale-y: var(--iso-scale);
|
|
--face-stack-shift: 0;
|
|
pointer-events: none;
|
|
padding: 0.1rem;
|
|
font-family: var(--font-mono);
|
|
font-size: var(--font-size-xs);
|
|
font-weight: 450;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
|
|
&.top {
|
|
justify-content: center;
|
|
text-transform: uppercase;
|
|
}
|
|
&.right {
|
|
justify-content: space-between;
|
|
}
|
|
&.left {
|
|
justify-content: center;
|
|
}
|
|
|
|
p {
|
|
margin: 0;
|
|
}
|
|
}
|
|
|
|
.top,
|
|
.bottom {
|
|
--face-orient: rotate(30deg) skewX(-30deg);
|
|
--face-scale-y: var(--iso-scale);
|
|
}
|
|
.right,
|
|
.rear-left {
|
|
--face-orient: rotate(-30deg) skewX(-30deg);
|
|
}
|
|
.left,
|
|
.rear-right {
|
|
--face-orient: rotate(30deg) skewX(30deg);
|
|
}
|
|
.top,
|
|
.rear-right {
|
|
--face-y: calc(var(--face-stack-shift) - var(--iso-scale));
|
|
}
|
|
.left,
|
|
.rear-left {
|
|
--face-y: var(--face-stack-shift);
|
|
}
|
|
.right {
|
|
--face-y: calc(var(--face-stack-shift) + var(--iso-scale));
|
|
}
|
|
.bottom {
|
|
--face-y: 0;
|
|
}
|
|
.top {
|
|
--face-color: var(--face-top);
|
|
--face-x: 0;
|
|
}
|
|
.bottom {
|
|
--face-color: var(--face-bottom);
|
|
--face-x: 1;
|
|
}
|
|
.right {
|
|
--face-color: var(--face-right);
|
|
--face-x: 1;
|
|
}
|
|
.left {
|
|
--face-color: var(--face-left);
|
|
--face-x: 0;
|
|
}
|
|
.rear-right {
|
|
--face-color: var(--face-left);
|
|
--face-x: 1;
|
|
}
|
|
.rear-left {
|
|
--face-color: var(--face-top);
|
|
--face-x: 1;
|
|
--face-scale-x: -1;
|
|
}
|
|
.liquid.top {
|
|
--face-x: calc(1 - var(--fill));
|
|
}
|
|
}
|
|
|
|
@keyframes cube-pulse {
|
|
0%,
|
|
100% {
|
|
--pulse-mix: 0.5;
|
|
}
|
|
50% {
|
|
--pulse-mix: 1;
|
|
}
|
|
}
|