{"spec_id":"line-stepwise","library":"makie","language":"julia","code":"# anyplot.ai\n# line-stepwise: Step Line Plot\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 92/100 | Created: 2026-09-05\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 INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\n\n# Imprint categorical palette — first series is always brand green\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\", colorant\"#4467A3\", colorant\"#BD8233\",\n    colorant\"#AE3030\", colorant\"#2ABCCD\", colorant\"#954477\", colorant\"#99B314\",\n]\nconst BRAND = IMPRINT_PALETTE[1]\n\n# --- Data ---------------------------------------------------------------\n# Warehouse pallet inventory over a 24h operating day: each delivery or\n# outgoing shipment nudges the stock level, which then holds constant until\n# the next event — a natural fit for a post-aligned step plot. Gaps between\n# events are floored so clusters of near-simultaneous jumps don't muddy the\n# step shape.\nn_events = 46\nmin_gap = 0.18\ngaps = min_gap .+ rand(n_events) .* (24 / n_events - min_gap) * 1.8\nevent_hours = cumsum(gaps)\nevent_hours = event_hours[event_hours .< 24]\nhour = vcat(0.0, event_hours, 24.0)\n\nstock = zeros(Int, length(hour))\nstock[1] = 950\nfor i in 2:length(stock)-1\n    jump = rand() < 0.55 ? rand(20:80) : -rand(20:80)\n    stock[i] = clamp(stock[i-1] + jump, 400, 1600)\nend\nstock[end] = stock[end-1]\n\npeak_idx = argmax(stock)\npeak_hour, peak_stock = hour[peak_idx], stock[peak_idx]\n\n# --- Plot -----------------------------------------------------------------\nfig = Figure(\n    resolution      = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"line-stepwise · julia · makie · anyplot.ai\",\n    titlesize          = 25,\n    titlecolor         = INK,\n    xlabel             = \"Hour of Day\",\n    ylabel             = \"Pallets in Stock\",\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    xticks             = 0:6:24,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridvisible       = false,\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    yminorgridvisible  = false,\n)\n\nstairs!(ax, hour, stock; step = :post, color = BRAND, linewidth = 3.0)\n\n# Focal point: call out the peak stock level reached during the day\nscatter!(ax, [peak_hour], [peak_stock]; color = BRAND, markersize = 12, strokewidth = 2, strokecolor = PAGE_BG)\ntext!(\n    ax, peak_hour, peak_stock;\n    text = \"Peak: $(peak_stock) pallets\",\n    color = INK,\n    fontsize = 13,\n    align = (peak_hour > 20 ? :right : :left, :bottom),\n    offset = (peak_hour > 20 ? -10 : 10, 8),\n)\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}