{"spec_id":"scatter-connected-temporal","library":"makie","language":"julia","code":"# anyplot.ai\n# scatter-connected-temporal: Connected Scatter Plot with Temporal Path\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 91/100 | Created: 2026-06-09\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\n\n# Theme tokens — Imprint palette\nconst THEME       = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG     = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst ELEVATED_BG = THEME == \"light\" ? colorant\"#FFFDF6\" : colorant\"#242420\"\nconst INK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst INK_MUTED   = THEME == \"light\" ? colorant\"#6B6A63\" : colorant\"#A8A79F\"\n\n# Imprint sequential colormap — early (green) → late (blue) encodes temporal direction\nconst ANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])\n\n# Data — synthetic annual CO₂ concentration vs global temperature anomaly (1980–2022)\nyears = collect(1980:2022)\nn     = length(years)\n\nco2  = 338.0 .+ (years .- 1980) .* 1.9  .+ randn(n) .* 0.6\ntemp = 0.10  .+ (years .- 1980) .* 0.018 .+ randn(n) .* 0.06\n\n# Temporal position [0, 1] for colormap\nt_norm = (years .- years[1]) ./ (years[end] - years[1])\n\n# Key year annotations (1-based: 1980, 1990, 2000, 2010, 2022)\nkey_idx = [1, 11, 21, 31, 43]\n\n# Title — descriptive prefix added; scale fontsize to avoid overflow\ntitle_str = \"CO₂ vs Temperature · scatter-connected-temporal · julia · makie · anyplot.ai\"\ntitle_n   = length(title_str)\ntitle_sz  = max(14, round(Int, 20 * 67 / title_n))\n\n# Figure\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = title_str,\n    titlesize          = title_sz,\n    titlecolor         = INK,\n    xlabel             = \"Atmospheric CO₂ (ppm)\",\n    ylabel             = \"Temperature Anomaly (°C)\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xtickcolor         = INK_SOFT,\n    ytickcolor         = INK_SOFT,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.12),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.12),\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n)\n\n# Temporal path — one segment per year pair, colored by midpoint time position\nfor i in 1:(n - 1)\n    mid_t = (t_norm[i] + t_norm[i + 1]) / 2\n    lines!(ax, [co2[i], co2[i + 1]], [temp[i], temp[i + 1]];\n        color     = ANYPLOT_SEQ[mid_t],\n        linewidth = 2.5,\n    )\nend\n\n# Scatter points — colored by temporal position via Imprint sequential colormap\nsc = scatter!(ax, co2, temp;\n    color       = t_norm,\n    colormap    = ANYPLOT_SEQ,\n    markersize  = 14,\n    strokewidth = 1.0,\n    strokecolor = PAGE_BG,\n)\n\n# Directional arrow at temporal start (1980) — scaled to 6% of each axis span for visibility\nlet\n    co2_span  = maximum(co2) - minimum(co2)\n    temp_span = maximum(temp) - minimum(temp)\n    dx = co2[2] - co2[1]\n    dy = temp[2] - temp[1]\n    nx = dx / co2_span\n    ny = dy / temp_span\n    len = sqrt(nx^2 + ny^2)\n    scale = 0.06\n    arrows!(ax, [co2[1]], [temp[1]], [nx / len * scale * co2_span], [ny / len * scale * temp_span];\n        arrowsize = 16,\n        color     = ANYPLOT_SEQ[0.0],\n        linewidth = 2.0,\n    )\nend\n\n# Key year labels at notable positions\nfor ki in key_idx\n    text!(ax, co2[ki], temp[ki];\n        text     = string(years[ki]),\n        fontsize = 13,\n        color    = INK,\n        align    = (:center, :bottom),\n        offset   = (0, 8),\n    )\nend\n\n# Colorbar — shows year range encoded by the temporal gradient\nColorbar(fig[1, 2];\n    colormap       = ANYPLOT_SEQ,\n    limits         = (Float64(years[1]), Float64(years[end])),\n    label          = \"Year\",\n    labelcolor     = INK,\n    ticklabelcolor = INK_SOFT,\n    tickcolor      = INK_SOFT,\n    ticklabelsize  = 11,\n    labelsize      = 13,\n    width          = 18,\n)\n\ncolgap!(fig.layout, 1, 20)\n\n# Save\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}