Dotted-graticule globe with stroke-dashed arcs and endpoint pings.
<!doctype html>
<!-- Example: globe-arcs — dotted graticule + arcs with stroke-dasharray + endpoint pings -->
<html data-duration="9" data-aspect="16:9"><head><style>
:root {
--cream:#f6f5f1; --cream-2:#efece4; --ink:#0a0a0a; --mute:#6b6862;
--line:#e3dfd3; --signal:#ff3b1f; --signal-2:#ff6a4a; --frame:#ffb800;
--green:#1f8a5b; --blue:#2b66ff;
}
* { box-sizing: border-box; }
body { margin:0; }
body { background: var(--ink); color: var(--cream); height: 100vh;
display: grid; place-items: center; font-family: ui-monospace, monospace; }
svg { width: 720px; height: 720px; }
.globe { fill: #0d0d14; stroke: rgba(255,255,255,.10); stroke-width: 1; }
.grat { fill: none; stroke: rgba(255,255,255,.10); stroke-width: 1;
stroke-dasharray: 1 4; }
.arc { fill: none; stroke: var(--signal); stroke-width: 2; stroke-linecap: round;
filter: drop-shadow(0 0 6px rgba(255,59,31,.7)); }
.node { fill: var(--signal); }
.ping { fill: rgba(255,59,31,.5); }
.label { font-size: 11px; fill: rgba(255,255,255,.55); letter-spacing: .2em; }
.cap { fill: rgba(255,255,255,.45); font-size: 10px; letter-spacing: .25em; }
</style></head><body>
<svg viewBox="-200 -200 400 400">
<circle class="globe" cx="0" cy="0" r="170"/>
<ellipse class="grat" cx="0" cy="0" rx="170" ry="50"/>
<ellipse class="grat" cx="0" cy="0" rx="170" ry="100"/>
<ellipse class="grat" cx="0" cy="0" rx="170" ry="150"/>
<ellipse class="grat" cx="0" cy="0" rx="50" ry="170"/>
<ellipse class="grat" cx="0" cy="0" rx="100" ry="170"/>
<ellipse class="grat" cx="0" cy="0" rx="150" ry="170"/>
<line class="grat" x1="0" y1="-170" x2="0" y2="170"/>
<line class="grat" x1="-170" y1="0" x2="170" y2="0"/>
<g id="arcs"></g>
<g id="nodes"></g>
<g id="pings"></g>
<text class="label" x="-180" y="190">● HF · WORLD MESH</text>
<text class="cap" x="120" y="190" text-anchor="end">6 arcs · 8 nodes · live</text>
</svg>
<script>
var PTS = [
[-140, -52], [100, -38], [-38, 78], [76, 88], [-114, 64],
[150, 38], [-28, -100], [40, -120]
];
var PAIRS = [[0,1],[2,3],[0,4],[5,2],[3,5],[6,7]];
var SVGNS = 'http://www.w3.org/2000/svg';
var arcs = document.getElementById('arcs');
var nodes = document.getElementById('nodes');
var pings = document.getElementById('pings');
PTS.forEach(function(p, i) {
var c = document.createElementNS(SVGNS, 'circle');
c.setAttribute('cx', p[0]); c.setAttribute('cy', p[1]); c.setAttribute('r', 3.4);
c.setAttribute('class', 'node');
nodes.appendChild(c);
// Ping ring (animated via attr).
var pg = document.createElementNS(SVGNS, 'circle');
pg.setAttribute('cx', p[0]); pg.setAttribute('cy', p[1]);
pg.setAttribute('r', 0); pg.setAttribute('class', 'ping');
pg.setAttribute('data-idx', i);
pings.appendChild(pg);
});
var arcEls = PAIRS.map(function(pair) {
var a = PTS[pair[0]], b = PTS[pair[1]];
var mx = (a[0] + b[0]) / 2, my = (a[1] + b[1]) / 2;
var len = Math.hypot(b[0] - a[0], b[1] - a[1]);
var cx = mx, cy = my - len * 0.55;
var d = 'M' + a[0] + ' ' + a[1] + ' Q ' + cx + ' ' + cy + ' ' + b[0] + ' ' + b[1];
var p = document.createElementNS(SVGNS, 'path');
p.setAttribute('class', 'arc'); p.setAttribute('d', d);
arcs.appendChild(p);
var total = p.getTotalLength();
p.setAttribute('stroke-dasharray', total);
p.setAttribute('stroke-dashoffset', total);
return { el: p, total: total, end: pair[1] };
});
var t = 0;
var reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
function render() {
var tt = reduced ? 4 : t;
arcEls.forEach(function(a, i) {
var start = i * 0.45;
var u = Math.max(0, Math.min(1, (tt - start) / 1.3));
a.el.setAttribute('stroke-dashoffset', a.total * (1 - u));
// When arc completes, ping the endpoint.
var pingPhase = Math.max(0, Math.min(1, (tt - start - 1.3) / 0.9));
var pg = pings.children[a.end];
if (pg && pingPhase > 0 && pingPhase < 1) {
pg.setAttribute('r', String(3.4 + pingPhase * 20));
pg.setAttribute('opacity', String(1 - pingPhase));
}
});
}
addEventListener('hf-seek', function(e) { t = e.detail.time; render(); });
render();
</script>
</body></html>