{"spec_id":"line-markers","library":"makie","language":"julia","code":"# anyplot.ai\n# line-markers: Line Plot with Markers\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 85/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\"\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\",\n]\n\n# --- Data ---------------------------------------------------------------\n# Quality-control readings: two production lines sampled at hourly checkpoints.\nhours = 0:11\nline_a = 98.2 .+ cumsum(randn(length(hours)) .* 0.6)\nline_b = 96.8 .+ cumsum(randn(length(hours)) .* 0.6)\n\n# Locate the first crossing between the two lines for a storytelling annotation.\ndiffs = line_a .- line_b\ncross_i = findfirst(i -> sign(diffs[i]) != sign(diffs[i + 1]), 1:(length(diffs) - 1))\nif cross_i !== nothing\n    t = diffs[cross_i] / (diffs[cross_i] - diffs[cross_i + 1])\n    cross_x = hours[cross_i] + t * (hours[cross_i + 1] - hours[cross_i])\n    cross_y = line_a[cross_i] + t * (line_a[cross_i + 1] - line_a[cross_i])\nend\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-markers · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Inspection Hour\",\n    ylabel             = \"Yield (%)\",\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    xgridvisible       = false,\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    xticks             = collect(hours),\n)\n\nscatterlines!(ax, hours, line_a; color = IMPRINT_PALETTE[1], linewidth = 3,\n              marker = :circle, markersize = 16, strokewidth = 1.5,\n              strokecolor = PAGE_BG, label = \"Line A\")\n\nscatterlines!(ax, hours, line_b; color = IMPRINT_PALETTE[2], linewidth = 3,\n              marker = :utriangle, markersize = 18, strokewidth = 1.5,\n              strokecolor = PAGE_BG, label = \"Line B\")\n\nif cross_i !== nothing\n    scatter!(ax, [cross_x], [cross_y]; color = :transparent, marker = :circle,\n              markersize = 30, strokewidth = 2, strokecolor = INK_SOFT)\n    text!(ax, cross_x, cross_y; text = \"crossover\", color = INK_SOFT,\n          fontsize = 12, align = (:center, :bottom), offset = (0, 16))\nend\n\naxislegend(ax; position = :rb, labelcolor = INK_SOFT, framevisible = false)\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}