Twisting puzzle cube
Pure CSSA 3×3×3 cube built as three layers that take turns twisting a quarter turn. Each layer is one flat box with the stickers painted on by gradients.
A glass pyramid with a glowing core: triangles cut with clip-path, leaned inward by exactly the angle that makes the tips meet.
Your edited version
clip-path: polygon(50% 0, 0 100%, 100% 100%).rotateY(n × 90deg) translateZ(base / 2) puts it on one side of the floor.rotateX with transform-origin: bottom leans it inward. The angle that makes all four tips meet is asin((base / 2) / slant): 30° when base and slant height are equal.rotateY(-360deg) on the same timing), so it always faces you and stays round.--u, so the pyramid is the same share of a gallery card, the editor and a recording canvas. The base is 140 of those units.clip-path: polygon()transform-origin: bottomlean angle = asin((base / 2) / slant)<div class="scene">
<div class="pyramid">
<i></i><i></i><i></i><i></i>
<b></b>
<u></u>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the pyramid is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.36vmin;
perspective: calc(800 * var(--u));
}
.pyramid {
--base: calc(140 * var(--u));
position: relative;
width: var(--base);
height: var(--base); /* slant height = base → lean is exactly 30deg */
transform-style: preserve-3d;
animation: pyramid-spin 12s linear infinite;
}
/* glass faces: see-through, so the far faces and the core show through */
.pyramid i {
--c: #2ee6d6;
position: absolute;
inset: 0;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
transform-origin: bottom center;
background:
linear-gradient(90deg, transparent 44%, rgb(255 255 255 / 0.18) 50%, transparent 56%),
linear-gradient(color-mix(in srgb, var(--c) 78%, transparent), rgb(139 108 255 / 0.22));
}
.pyramid i:nth-child(even) {
--c: #ff4d9d;
}
.pyramid i:nth-child(1) { transform: rotateY(0deg) translateZ(calc(var(--base) / 2)) rotateX(30deg); }
.pyramid i:nth-child(2) { transform: rotateY(90deg) translateZ(calc(var(--base) / 2)) rotateX(30deg); }
.pyramid i:nth-child(3) { transform: rotateY(180deg) translateZ(calc(var(--base) / 2)) rotateX(30deg); }
.pyramid i:nth-child(4) { transform: rotateY(270deg) translateZ(calc(var(--base) / 2)) rotateX(30deg); }
/* floor: dark glass with a glowing rim. The rim is an inset line plus a soft shade, not a
border: the floor is seen nearly side-on, and a 1px border squeezed that flat breaks into dashes */
.pyramid b {
position: absolute;
inset: auto 0 0;
height: var(--base);
background: rgb(139 108 255 / 0.3);
box-shadow:
inset 0 0 0 calc(1.5 * var(--u)) rgb(46 230 214 / 0.7),
inset 0 0 calc(6 * var(--u)) rgb(46 230 214 / 0.7),
0 0 calc(34 * var(--u)) rgb(139 108 255 / 0.6);
transform: translateY(50%) rotateX(90deg);
}
/* the core: a third of the way up (the pyramid stands base × cos 30deg ≈ 121 units tall). It
turns back against the spin, so it always faces you and stays round. */
.pyramid u {
position: absolute;
top: calc(101 * var(--u));
left: 50%;
width: calc(36 * var(--u));
height: calc(36 * var(--u));
margin: calc(-18 * var(--u)) 0 0 calc(-18 * var(--u));
border-radius: 50%;
background: radial-gradient(circle, #fff 0 18%, #ffb547 42%, transparent 72%);
animation: face-you 12s linear infinite, pulse 2.4s ease-in-out infinite alternate;
}
@keyframes pyramid-spin {
from { transform: translateY(calc(-20 * var(--u))) rotateX(-16deg) rotateY(0deg); }
to { transform: translateY(calc(-20 * var(--u))) rotateX(-16deg) rotateY(360deg); }
}
@keyframes face-you {
from { transform: rotateY(0deg); }
to { transform: rotateY(-360deg); }
}
@keyframes pulse {
from { opacity: 0.75; scale: 0.85; }
to { opacity: 1; scale: 1.15; }
}