spb/satelliteindex
Public
TypeScript 66.5%
Python 30.9%
JavaScript 1.4%
CSS 0.7%
1import Link from 'next/link';2import { cn } from '@/lib/cn';3import { routes } from '@/lib/site';45/** Immediate shell while the 3D bundle loads: a dark disc with the accent limb so the layout never jumps. */6export function GlobeSkeleton({ className, label = 'Loading globe…' }: { className?: string; label?: string }) {7 return (8 <div className={cn('relative flex h-full w-full items-center justify-center overflow-hidden', className)} aria-busy="true" aria-live="polite">9 <div10 className="aspect-square w-[min(72%,520px)] rounded-full"11 style={{12 background: 'radial-gradient(circle at 35% 30%, rgba(24,33,64,0.9), rgba(11,16,32,0.95) 55%, rgba(6,9,18,1) 72%)',13 boxShadow: '0 0 0 1px rgba(56,211,255,0.10), 0 0 60px rgba(56,211,255,0.10), inset -30px -20px 80px rgba(0,0,0,0.5)',14 }}15 />16 <p className="mono absolute bottom-4 left-4 text-2xs uppercase tracking-[0.14em] text-ink-3">{label}</p>17 </div>18 );19}2021/** Honest fallback when WebGL is unavailable (headless, blocked GPU, old device). */22export function GlobeUnavailable({ className, reason }: { className?: string; reason?: string }) {23 return (24 <div className={cn('flex h-full w-full items-center justify-center p-6', className)} role="status">25 <div className="max-w-sm text-center">26 <p className="eyebrow">3D globe</p>27 <p className="mt-2 text-base font-medium text-ink">WebGL is not available in this browser</p>28 <p className="mt-2 text-sm leading-relaxed text-ink-3">{reason ?? 'The live globe needs hardware-accelerated graphics. Positions and orbital data are still available in the catalogue.'}</p>29 <Link href={routes.satellites('has_gp=true')} className="mt-4 inline-flex h-11 items-center justify-center rounded-md border border-rule-strong px-4 text-sm text-ink hover:bg-plane-2">30 Browse tracked satellites →31 </Link>32 </div>33 </div>34 );35}36