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.
Nine circles rotated around the Y axis make the meridians; one laid flat is the equator.
Your edited version
border-radius: 50% and only an edge line. The line is an inset box-shadow with a soft glow, not a border: a ring turned nearly side-on is squeezed to a pixel or two, and a hard 1.5px border breaks into dots there.i × 20deg around Y, form the meridians. 9 × 20° = 180° is enough because each ring is visible on both sides.rotateX(90deg) is the equator.rotateZ before the animated rotateY gives the tilted-axis look.--u, so the globe is the same share of a gallery card, the editor and a recording canvas. The sphere is 200 of those units across, and the camera sits 800 back — close enough that the near side is magnified, which is what the base unit has to leave room for.border-radius: 50% ringsrotateY(i × 20deg)preserve-3d spin<div class="scene">
<div class="globe">
<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>
<i style="--i:6"></i>
<i style="--i:7"></i>
<i style="--i:8"></i>
<b></b>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the globe is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.29vmin;
perspective: calc(800 * var(--u));
}
.globe {
position: relative;
width: calc(200 * var(--u));
height: calc(200 * var(--u));
transform-style: preserve-3d;
animation: globe-spin 14s linear infinite;
}
/* the line is an inset shadow with a soft glow, not a border: a ring nearly side-on is squeezed
to a pixel or two, and a hard border breaks into dots there. The glow keeps it whole. */
.globe i,
.globe b {
--c: #2ee6d6;
position: absolute;
inset: 0;
border-radius: 50%;
box-shadow:
inset 0 0 0 calc(1.5 * var(--u)) var(--c),
inset 0 0 calc(2 * var(--u)) calc(1.5 * var(--u)) color-mix(in srgb, var(--c) 40%, transparent),
0 0 calc(2 * var(--u)) color-mix(in srgb, var(--c) 50%, transparent);
}
.globe i { transform: rotateY(calc(var(--i) * 20deg)); } /* meridians */
.globe b { transform: rotateX(90deg); --c: #ff4d9d; } /* equator */
@keyframes globe-spin {
from { transform: rotateZ(18deg) rotateX(-14deg) rotateY(0deg); }
to { transform: rotateZ(18deg) rotateX(-14deg) rotateY(360deg); }
}