{"spec_id":"bifurcation-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# bifurcation-basic: Bifurcation Diagram for Dynamical Systems\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 91/100 | Created: 2026-06-17\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\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\",\n    colorant\"#C475FD\",\n    colorant\"#4467A3\",\n    colorant\"#BD8233\",\n    colorant\"#AE3030\",\n    colorant\"#2ABCCD\",\n    colorant\"#954477\",\n    colorant\"#99B314\",\n]\n\n# Data — logistic map: x(n+1) = r * x(n) * (1 - x(n))\nn_r    = 2000\nn_warm = 200\nn_keep = 100\n\nr_values = LinRange(2.5, 4.0, n_r)\nr_pts    = Float64[]\nx_pts    = Float64[]\nsizehint!(r_pts, n_r * n_keep)\nsizehint!(x_pts, n_r * n_keep)\n\nfor r in r_values\n    x = 0.5\n    for _ in 1:n_warm\n        x = r * x * (1.0 - x)\n    end\n    for _ in 1:n_keep\n        x = r * x * (1.0 - x)\n        push!(r_pts, r)\n        push!(x_pts, x)\n    end\nend\n\n# Custom Makie theme — anyplot chrome tokens applied via with_theme\nanyplot_theme = Theme(\n    fontsize = 14,\n    Axis = (\n        backgroundcolor   = PAGE_BG,\n        titlecolor        = INK,\n        titlesize         = 20,\n        xlabelcolor       = INK,\n        ylabelcolor       = INK,\n        xlabelsize        = 14,\n        ylabelsize        = 14,\n        xticklabelcolor   = INK_SOFT,\n        yticklabelcolor   = INK_SOFT,\n        xticklabelsize    = 12,\n        yticklabelsize    = 12,\n        xtickcolor        = INK_SOFT,\n        ytickcolor        = INK_SOFT,\n        leftspinecolor    = INK_SOFT,\n        bottomspinecolor  = INK_SOFT,\n        topspinevisible   = false,\n        rightspinevisible = false,\n        xgridvisible      = false,\n        ygridvisible      = false,\n    ),\n)\n\nwith_theme(anyplot_theme) do\n    fig = Figure(\n        size            = (1600, 900),\n        backgroundcolor = PAGE_BG,\n    )\n\n    ax = Axis(\n        fig[1, 1];\n        title  = \"bifurcation-basic · julia · makie · anyplot.ai\",\n        xlabel = \"Growth rate  r\",\n        ylabel = \"Population x\",\n    )\n\n    # Subtle shading for the chaotic regime (Feigenbaum onset r ≈ 3.57)\n    chaotic_poly = Point2f[(3.57, 0.0), (4.0, 0.0), (4.0, 1.05), (3.57, 1.05)]\n    poly!(ax, chaotic_poly; color = (INK, 0.04), strokewidth = 0)\n\n    # Density scatter — slightly higher alpha for dark theme to preserve contrast\n    pt_alpha = THEME == \"dark\" ? 0.13 : 0.10\n    scatter!(ax, r_pts, x_pts;\n        color       = (IMPRINT_PALETTE[1], pt_alpha),\n        markersize  = 1.0,\n        strokewidth = 0,\n    )\n\n    ylims!(ax, 0.0, 1.05)\n\n    # Bifurcation point labels — period-doubling cascade\n    bif_r      = [3.0,        3.449,      3.544]\n    bif_labels = [\"Period-2\", \"Period-4\", \"Period-8\"]\n    bif_y      = [0.93,       0.86,       0.93]\n\n    for (r_val, label, y_pos) in zip(bif_r, bif_labels, bif_y)\n        vlines!(ax, [r_val];\n            color     = (INK_SOFT, 0.5),\n            linewidth = 1.0,\n            linestyle = :dash,\n        )\n        text!(ax, label;\n            position = (r_val, y_pos),\n            align    = (:center, :bottom),\n            fontsize = 12,\n            color    = INK_SOFT,\n        )\n    end\n\n    save(\"plot-$(THEME).png\", fig; px_per_unit = 2)\nend\n"}