{"spec_id":"bump-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# bump-basic: Basic Bump Chart\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 88/100 | Created: 2026-05-29\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\n\n# Theme tokens\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 GRID_INK    = THEME == \"light\" ?\n    RGBAf(26 / 255, 26 / 255, 23 / 255, 0.12) :\n    RGBAf(240 / 255, 239 / 255, 232 / 255, 0.12)\n\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\",\n    colorant\"#C475FD\",\n    colorant\"#4467A3\",\n    colorant\"#BD8233\",\n    colorant\"#AE3030\",\n    colorant\"#2ABCCD\",\n]\n\n# Data — tech startup investor-ranking competition, Q1 2023 to Q2 2024\ncompanies = [\"NovaTech\", \"PulseAI\", \"CircleCloud\", \"ApexRobotics\", \"QuantumIO\", \"ShieldSec\"]\nquarters  = [\"Q1'23\", \"Q2'23\", \"Q3'23\", \"Q4'23\", \"Q1'24\", \"Q2'24\"]\nn_periods   = length(quarters)\nn_companies = length(companies)\n\n# Rankings matrix (rows = companies, cols = quarters); 1 = highest rank\nrankings = [\n    2  1  1  1  1  2;   # NovaTech:     rises to top, then slips\n    4  3  2  2  2  1;   # PulseAI:      steadily climbs to #1\n    1  2  3  3  3  3;   # CircleCloud:  leads early, then fades\n    3  4  4  4  4  4;   # ApexRobotics: stable mid-pack\n    6  5  5  5  5  5;   # QuantumIO:    slight recovery\n    5  6  6  6  6  6;   # ShieldSec:    slides to last\n]\n\nx = Float64.(1:n_periods)\n\n# Plot\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"bump-basic · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Quarter\",\n    ylabel             = \"Rank\",\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    xticks             = (x, quarters),\n    yticks             = 1:n_companies,\n    yreversed          = true,\n    xgridvisible       = false,\n    ygridvisible       = true,\n    ygridcolor         = GRID_INK,\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n    limits             = (0.3, n_periods + 1.1, nothing, nothing),\n)\n\nfor i in 1:n_companies\n    ranks = Float64.(rankings[i, :])\n    color = IMPRINT_PALETTE[i]\n    # Thicker stroke on the two most dramatic arcs: PulseAI (#1 climber) and CircleCloud (biggest faller)\n    lw = (i == 2 || i == 3) ? 4.5 : 3.0\n    lines!(ax, x, ranks; color = color, linewidth = lw)\n    scatter!(ax, x, ranks;\n        color       = color,\n        markersize  = 16,\n        strokecolor = PAGE_BG,\n        strokewidth = 2,\n    )\n    # Endpoint rank callouts via Makie's text! — surface final positions for storytelling\n    text!(ax, n_periods + 0.18, Float64(rankings[i, end]);\n        text     = \"#$(rankings[i, end])\",\n        fontsize = 11,\n        color    = color,\n        align    = (:left, :center),\n    )\nend\n\nlegend_elements = [LineElement(color = IMPRINT_PALETTE[i], linewidth = 3.0) for i in 1:n_companies]\nLegend(\n    fig[1, 2],\n    legend_elements,\n    companies;\n    backgroundcolor = ELEVATED_BG,\n    framecolor      = INK_SOFT,\n    labelcolor      = INK,\n)\n\n# Proportion the legend column to ~18% of figure width using colsize!\ncolsize!(fig.layout, 2, Relative(0.18))\n\n# Save\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}