{"spec_id":"bar-heart-rate-zones","library":"makie","language":"julia","code":"# anyplot.ai\n# bar-heart-rate-zones: Time in Heart Rate Zones Bar Chart\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 88/100 | Created: 2026-06-14\n\nusing CairoMakie\nusing Colors\n\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 INK_MUTED = THEME == \"light\" ? colorant\"#6B6A63\" : colorant\"#A8A79F\"\n\n# Semantic zone colors: conventional fitness zone color scheme (semantic exception)\n# Z1→grey/muted, Z2→Imprint blue, Z3→Imprint green, Z4→Imprint ochre, Z5→Imprint red\nconst ZONE_COLORS = [\n    INK_MUTED,           # Z1 Recovery  — grey (theme-adaptive muted)\n    colorant\"#4467A3\",   # Z2 Endurance — Imprint blue\n    colorant\"#009E73\",   # Z3 Aerobic   — Imprint brand green\n    colorant\"#BD8233\",   # Z4 Threshold — Imprint ochre\n    colorant\"#AE3030\",   # Z5 Maximum   — Imprint matte red\n]\n\n# Data — 90-minute endurance ride\nconst ZONE_POS    = [1, 2, 3, 4, 5]\nconst MINUTES     = [10.0, 48.0, 20.0, 10.0, 2.0]\nconst TOTAL_MIN   = sum(MINUTES)\nconst ZONE_LABELS = [\"Z1\\nRecovery\", \"Z2\\nEndurance\", \"Z3\\nAerobic\", \"Z4\\nThreshold\", \"Z5\\nMaximum\"]\n\nconst TITLE_STR = \"90-Min Endurance Ride · bar-heart-rate-zones · julia · makie · anyplot.ai\"\nconst TITLESIZE = round(Int, 20 * min(1.0, 67 / length(TITLE_STR)))\n\nfig = Figure(size = (1600, 900), fontsize = 14, backgroundcolor = PAGE_BG)\n\nax = Axis(\n    fig[1, 1];\n    title              = TITLE_STR,\n    titlesize          = TITLESIZE,\n    titlefont          = :bold,\n    titlecolor         = INK,\n    xlabel             = \"Heart Rate Zone\",\n    ylabel             = \"Time (minutes)\",\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    yminorgridvisible  = false,\n    xminorgridvisible  = false,\n    xticks             = (ZONE_POS, ZONE_LABELS),\n)\n\nbarplot!(ax, ZONE_POS, MINUTES; color = ZONE_COLORS, width = 0.65, strokewidth = 0)\n\n# Duration + percentage breakdown labels above each bar\n# Dominant zone (Z2) rendered in zone color and bold for storytelling emphasis\nfor (i, m) in enumerate(MINUTES)\n    pct = round(Int, 100 * m / TOTAL_MIN)\n    if i == 2  # Z2 Endurance — dominant zone\n        text!(ax, i, m + 1.2;\n            text     = \"$(Int(m)) min\\n$(pct)%\",\n            align    = (:center, :bottom),\n            fontsize = 13,\n            color    = ZONE_COLORS[2],\n            font     = :bold,\n        )\n    else\n        text!(ax, i, m + 1.2;\n            text     = \"$(Int(m)) min\\n$(pct)%\",\n            align    = (:center, :bottom),\n            fontsize = 12,\n            color    = INK,\n        )\n    end\nend\n\n# Dominant zone callout — session context in the upper-right open space\ntext!(ax, 5.38, maximum(MINUTES) * 1.25;\n    text  = \"Base endurance ride\\nZ2-heavy · 53% of session\",\n    align = (:right, :top),\n    fontsize = 11,\n    color    = INK_MUTED,\n    font     = :italic,\n)\n\nylims!(ax, 0, maximum(MINUTES) * 1.40)\n\n# HR zone boundary legend — Makie composable layout with PolyElement patches\nlegend_patches = [PolyElement(color = ZONE_COLORS[i], strokewidth = 0) for i in 1:5]\nlegend_labels = [\n    \"Z1 Recovery  < 60% HRmax\",\n    \"Z2 Endurance  60–70% HRmax\",\n    \"Z3 Aerobic  70–80% HRmax\",\n    \"Z4 Threshold  80–90% HRmax\",\n    \"Z5 Maximum  > 90% HRmax\",\n]\n\nLegend(fig[2, 1], legend_patches, legend_labels, \"HR Zone Boundaries\";\n    orientation  = :horizontal,\n    framevisible = false,\n    labelcolor   = INK_SOFT,\n    titlecolor   = INK_SOFT,\n    labelsize    = 10,\n    titlesize    = 11,\n    patchsize    = (20, 12),\n)\n\nrowsize!(fig.layout, 2, Relative(0.08))\nrowgap!(fig.layout, 6)\n\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}