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.
Five hexagonal prisms of different sizes growing from one rock at different tilts. Each side panel carries its own tip facet as a ::before, folded in so the six meet in a point.
Your edited version
--w wide in a closed ring, rotateY(i × 60deg) translateZ(w × 0.866). 0.866 is √3 / 2, the apothem of a hexagon with side w.::before. The panel gets transform-style: preserve-3d, so the triangle can fold in along the panel's top edge by 40°. Its height, apothem / sin(40°) = 1.347 × w, makes the six points meet on the axis.rotateY to face its direction, translateZ out from the centre, then rotateX to lean outward. Three numbers in each crystal's style attribute (--az, --off, --tilt) place all five.opacity would flatten its 3D children.--u, tied to the canvas, so the cluster is the same share of a gallery card, the editor and a recording canvas. The style attribute hands each crystal plain numbers, and CSS turns them into lengths by multiplying by --u.hexagon ring: apothem = side × √3 / 2tip facet as a folded ::beforerotateY · translateZ · rotateX to lean outcrossed glow planes<div class="scene">
<div class="cluster">
<b class="rock"></b>
<div class="crystal" style="--az:0deg; --off:0; --tilt:0deg; --w:22; --h:86; --c:#8b6cff; --c2:#ff4d9d; --d:0s">
<i style="--i:0"></i>
<i style="--i:1"></i>
<i style="--i:2"></i>
<i style="--i:3"></i>
<i style="--i:4"></i>
<i style="--i:5"></i>
<b></b>
</div>
<div class="crystal" style="--az:30deg; --off:16; --tilt:30deg; --w:15; --h:60; --c:#2ee6d6; --c2:#8b6cff; --d:-1.2s">
<i style="--i:0"></i>
<i style="--i:1"></i>
<i style="--i:2"></i>
<i style="--i:3"></i>
<i style="--i:4"></i>
<i style="--i:5"></i>
<b></b>
</div>
<div class="crystal" style="--az:115deg; --off:14; --tilt:26deg; --w:14; --h:50; --c:#ff4d9d; --c2:#8b6cff; --d:-2.4s">
<i style="--i:0"></i>
<i style="--i:1"></i>
<i style="--i:2"></i>
<i style="--i:3"></i>
<i style="--i:4"></i>
<i style="--i:5"></i>
<b></b>
</div>
<div class="crystal" style="--az:205deg; --off:16; --tilt:34deg; --w:16; --h:66; --c:#8b6cff; --c2:#2ee6d6; --d:-0.6s">
<i style="--i:0"></i>
<i style="--i:1"></i>
<i style="--i:2"></i>
<i style="--i:3"></i>
<i style="--i:4"></i>
<i style="--i:5"></i>
<b></b>
</div>
<div class="crystal" style="--az:290deg; --off:14; --tilt:30deg; --w:12; --h:40; --c:#2ee6d6; --c2:#ff4d9d; --d:-3s">
<i style="--i:0"></i>
<i style="--i:1"></i>
<i style="--i:2"></i>
<i style="--i:3"></i>
<i style="--i:4"></i>
<i style="--i:5"></i>
<b></b>
</div>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the cluster is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.44vmin;
perspective: calc(800 * var(--u));
}
.cluster {
position: relative;
width: 0;
height: 0;
transform-style: preserve-3d;
animation: spin 30s linear infinite;
}
/* stand on the floor (44 units down), face a direction, step out, lean outward */
.crystal {
/* the style attribute gives each crystal plain numbers; they become lengths here */
--wide: calc(var(--w) * var(--u));
--tall: calc(var(--h) * var(--u));
position: absolute;
transform-style: preserve-3d;
transform: translateY(calc(44 * var(--u))) rotateY(var(--az)) translateZ(calc(var(--off) * var(--u))) rotateX(calc(var(--tilt) * -1));
}
/* six side panels in a closed ring */
.crystal i {
position: absolute;
top: calc(var(--tall) * -1);
left: calc(var(--wide) / -2);
width: var(--wide);
height: var(--tall);
transform-style: preserve-3d; /* lets the tip fold in 3D */
transform: rotateY(calc(var(--i) * 60deg)) translateZ(calc(var(--wide) * 0.866));
background:
linear-gradient(90deg, transparent 30%, rgb(255 255 255 / 0.2) 42%, transparent 54%),
linear-gradient(to top, color-mix(in srgb, var(--c) 62%, transparent), color-mix(in srgb, var(--c) 14%, transparent) 70%, color-mix(in srgb, var(--c) 28%, transparent));
box-shadow:
inset calc(1 * var(--u)) 0 color-mix(in srgb, var(--c) 80%, transparent),
inset calc(-1 * var(--u)) 0 color-mix(in srgb, var(--c) 80%, transparent),
inset 0 calc(1 * var(--u)) color-mix(in srgb, var(--c) 85%, #fff);
}
.crystal i:nth-child(even) {
--c: var(--c2);
}
/* the tip facet: hinged on the panel's top edge, folded in by 40deg */
.crystal i::before {
--edge: color-mix(in srgb, var(--c) 85%, #fff);
content: '';
position: absolute;
bottom: 100%;
left: 0;
width: 100%;
height: calc(var(--wide) * 1.347); /* apothem / sin(40deg) */
transform-origin: 50% 100%;
transform: rotateX(40deg);
clip-path: polygon(50% 0, 0 100%, 100% 100%);
background:
linear-gradient(to top left, transparent calc(50% - 1 * var(--u)), var(--edge) calc(50% - 1 * var(--u)) 50%, transparent 50%) left / 50% 100% no-repeat,
linear-gradient(to top right, transparent calc(50% - 1 * var(--u)), var(--edge) calc(50% - 1 * var(--u)) 50%, transparent 50%) right / 50% 100% no-repeat,
linear-gradient(color-mix(in srgb, var(--c) 20%, #fff 30%), color-mix(in srgb, var(--c) 40%, transparent));
}
/* the inner glow: two crossed planes */
.crystal b {
position: absolute;
top: calc(var(--tall) * -1);
left: calc(var(--wide) * -0.8);
width: calc(var(--wide) * 1.6);
height: var(--tall);
transform-style: preserve-3d;
}
.crystal b::before,
.crystal b::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(50% 60% at 50% 72%, color-mix(in srgb, #fff 60%, var(--c)), color-mix(in srgb, var(--c) 45%, transparent) 40%, transparent);
animation: glow 3.6s ease-in-out var(--d) infinite alternate;
}
.crystal b::after {
transform: rotateY(90deg);
}
/* the rock: an uneven slab laid flat */
.rock {
position: absolute;
top: calc(-24 * var(--u));
left: calc(-68 * var(--u));
width: calc(136 * var(--u));
height: calc(136 * var(--u));
clip-path: polygon(22% 4%, 62% 0, 92% 18%, 100% 55%, 84% 90%, 46% 100%, 12% 86%, 0 48%);
background: radial-gradient(circle, #ae98ff 0 6%, #4a3e8d 24%, #2e2a5d 60%, #3c3576);
transform: translateY(calc(1 * var(--u))) rotateX(90deg);
}
@keyframes spin {
from { transform: rotateX(-22deg) rotateY(0deg); }
to { transform: rotateX(-22deg) rotateY(360deg); }
}
@keyframes glow {
from { opacity: 0.35; }
to { opacity: 1; }
}