/*
 * /thu-vien-ky-thuat/ — "26 ô tím" dome (engine "sphere"). Own HTML / CSS / JS for VNT39, written from the measured specification of the
 * reference demo (26 gradient tiles on a sphere, 26 s per turn, #16121E stage with a violet glow): no images, no React, no library.
 *
 * Motion and geometry = the demo's, unchanged (1u = the demo's 1px): the sphere is ONE 2 × 2 preserve-3d element that turns as a body
 * (rotateY 0 → 360deg with rotateX(-12deg), 26 s linear infinite); the tiles are flat 40 × 40 squares placed with translate3d(x, y, z) only, all with the same
 * orientation, backface-visibility hidden — so they tilt, thin out edge-on and disappear behind the sphere exactly like the demo (and, like the demo, the picture
 * is empty for part of each turn). Positions are printed by PHP from the demo's formula (golden-angle lattice, R 92, y × 0.7 − 18).
 * The whole cluster is scaled UNIFORMLY with its box (--u = a fixed fraction of the box's shorter side, container query unit). Tile size never depends on the text:
 * long names are shortened by PHP (full name in title / aria-label). The tiny script only pauses the animation off-screen / in a hidden tab.
 */
.tl-page .tl-sph { position: relative; min-width: 0; overflow: hidden; border-radius: 14px; background: #16121E; container-type: size; }
.tl-sph::before { content: ""; position: absolute; inset: 0; background: radial-gradient(120% 90% at 50% -10%, rgba(82, 39, 255, .10), transparent 62%); pointer-events: none; }

.tl-sph__scene { --u: calc(100cqmin / 270); position: absolute; inset: 0; display: grid; place-items: center; perspective: calc(560 * var(--u)); }
.tl-sph__ball { position: relative; width: 2px; height: 2px; transform-style: preserve-3d; animation: tl-sph-turn 26s linear infinite; }
.tl-page .tl-sph .tl-sph__t { position: absolute; display: grid; place-items: center; box-sizing: border-box; width: calc(40 * var(--u)); height: calc(40 * var(--u)); margin: calc(-20 * var(--u));
	padding: calc(2 * var(--u)) calc(1.5 * var(--u)); overflow: hidden; border-radius: calc(9 * var(--u)); border: 1px solid rgba(168, 85, 247, .4); background: linear-gradient(155deg, var(--a), var(--b));
	box-shadow: 0 0 calc(18 * var(--u)) calc(-8 * var(--u)) rgba(132, 0, 255, .9); backface-visibility: hidden;
	font: 600 calc(var(--fs) * var(--u)) / 1.12 ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace; font-style: normal; text-align: center; letter-spacing: 0; text-transform: none; overflow-wrap: normal; hyphens: none;
	color: rgba(255, 255, 255, .92); text-decoration: none;
	transform: translate3d(calc(var(--x) * var(--u)), calc(var(--y) * var(--u)), calc(var(--z) * var(--u))); }
.tl-page .tl-sph a.tl-sph__t { cursor: pointer; }
.tl-page .tl-sph a.tl-sph__t:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.tl-sph__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@keyframes tl-sph-turn { from { transform: rotateY(0deg) rotateX(-12deg); } to { transform: rotateY(360deg) rotateX(-12deg); } }

.tl-sph.is-paused .tl-sph__ball, .tl-sph.is-hidden .tl-sph__ball { animation-play-state: paused; }
@supports not (width: 1cqmin) { .tl-sph__scene { --u: 1.2px; } }
/* tablet / phone: the box is stacked under the text and shorter, so the cluster is scaled up a little to keep the names readable (still uniform) */
@media (max-width: 900px) { .tl-sph__scene { --u: calc(100cqmin / 240); } }
@media (prefers-reduced-motion: reduce) { .tl-sph__ball { animation: none; transform: rotateY(28deg) rotateX(-12deg); } }
