chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, svg_size, svg_size]);
var chart = { node: svg.node() };
var defs = svg.append('defs')
defs.append(hand_marker)
svg.append("circle")
.attr("r", svg_size / 2 - .5)
.attr("cx", svg_size / 2)
.attr("cy", svg_size / 2)
.attr("stroke", "#aaa")
.attr("fill", "#eee");
svg.append("circle")
.attr("r", radius_t)
.attr("cx", svg_size / 2)
.attr("cy", svg_size / 2)
.attr("stroke", "#aaa")
.attr("fill", "#ddd");
svg.append("circle")
.attr("r", radius)
.attr("cx", svg_size / 2)
.attr("cy", svg_size / 2)
.attr("fill", "#8af")
.attr("stroke", "none");
var clip_face = defs
.append('clipPath')
.attr('id', 'clip-face');
clip_face.append("circle")
.attr("r", radius)
.attr("cx", svg_size / 2)
.attr("cy", svg_size / 2);
var gClipped = svg.append("g")
.attr('clip-path', 'url(#clip-face)');
var gSky = gClipped.append("g");
chart.skyGrid = gSky.append("path")
.attr("fill", "none")
.attr("stroke", "white")
.attr("opacity", .3)
.attr("stroke-width", 1);
// celestial equator
chart.skyEq = gSky.append("path")
.attr("fill", "none")
.attr("stroke", "white")
.attr("opacity", 1)
.attr("stroke-width", 1);
// zenith
chart.z_char = put_char(gSky, "Z").attr("fill", "#fff");
var gEarth = gClipped.append("g");
chart.gEarth = gEarth;
chart.horizons = gEarth.append("g");
chart.earth_grid = gEarth.append("path")
.attr("fill", "none")
.attr("opacity", .3)
.attr("stroke", "white")
.attr("stroke-width", .5);
chart.nadir_char = put_char(gEarth, "👤")
.attr("font-size", 14);
chart.s_char = put_char(gEarth, "S")
.attr("font-size", 14).attr("fill", "#ec9");
chart.w_char = put_char(gEarth, "W")
.attr("font-size", 14).attr("fill", "#ec9");
chart.n_char = put_char(gEarth, "N")
.attr("font-size", 14).attr("fill", "#ec9");
chart.e_char = put_char(gEarth, "E")
.attr("font-size", 14).attr("fill", "#ec9");
var gSun = gClipped.append("g");
// sun track for today (appx.)
chart.sun_track = gSun.append("path")
.attr("fill", "none")
.attr("stroke", "#fe9")
.attr("opacity", 1)
.attr("stroke-width", 1)
.attr("stroke-dasharray", [3, 10]);
// moon track for today (appx.)
chart.moon_track = gSun.append("path")
.attr("fill", "none")
.attr("stroke", "#777")
.attr("opacity", 1)
.attr("stroke-width", 1)
.attr("stroke-dasharray", [3, 10]);
// sidereal time hands
// define hand length (for star) in image space:
chart.sidereal_1 = gSun.append("path")
.attr("fill", "none")
.attr("stroke", "#444")
.attr("opacity", 1)
.attr("stroke-width", 1);
chart.sidereal_2 = gSun.append("path")
.attr("fill", "none")
.attr("stroke", "#444")
.attr("opacity", 1)
.attr("stroke-width", 1);
chart.star = gSun.append(star_shape);
// ecliptic
chart.ecliptic = gSun.append("g");
// horoscope
chart.horoscope = gSun.append("g");
// dot in middle of hands
svg.append("circle")
.attr("r", 4)
.attr("cx", svg_size / 2)
.attr("cy", svg_size / 2)
.attr("fill", "black");
// border of clock face (has to be above the earth and sky fills)
svg.append("circle")
.attr("r", radius)
.attr("cx", svg_size / 2)
.attr("cy", svg_size / 2)
.attr("fill", "none")
.attr("stroke", "black");
// mean solar time scale
self.solar_time = new TimeScale(svg, radius, "#333", "#eee", d => roman_num(d), svg_size / 2);
self.solar_time.g_labels.style('letter-spacing', '-0.0625625em')
self.solar_time.g.append("g").attr("transform", `translate(-9, ${-radius - 23}) scale(${9/16})`).append(sun_shape);
// local time scale
chart.local_time = new TimeScale(svg, radius_t, "#777", "#fff", d => d, svg_size / 2);
var gHands = svg.append("g");
// sun hand
chart.sun_line = gHands.append("path")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("opacity", 1)
.attr("stroke-width", 2)
.attr("marker-end", "url(#hand-end)");
chart.sun = gHands.append("g").append(sun_shape);
// moon hand
// mean lunar time (without equation)
chart.moon_line = gHands.append("path")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("opacity", .7)
.attr("stroke-width", 1.5);
chart.moon = [gHands.append("circle"), gHands.append("path")]
return chart;
}