{"spec_id":"bar-heart-rate-zones","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' bar-heart-rate-zones: Time in Heart Rate Zones Bar Chart\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 91/100 | Created: 2026-06-14\n\nlibrary(ggplot2)\nlibrary(ragg)\n\n# Theme tokens\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nGRID_COLOR  <- if (THEME == \"light\") \"#D0CFC7\" else \"#3A3A36\"\n\n# Zone colors — semantic Imprint palette mapping (conventional HR zone hue associations):\n# Z1 recovery (grey) -> fixed #6B6A63  |  Z4 threshold (orange) -> Imprint ochre #BD8233\n# Z2 endurance (blue) -> Imprint #4467A3  |  Z5 maximum (red) -> semantic red #AE3030\n# Z3 aerobic (green) -> Imprint brand green #009E73\nZONE_COLORS <- c(\n  Z1 = \"#6B6A63\",\n  Z2 = \"#4467A3\",\n  Z3 = \"#009E73\",\n  Z4 = \"#BD8233\",\n  Z5 = \"#AE3030\"\n)\n\n# Data — 60-minute tempo run workout\nzones <- c(\"Z1\", \"Z2\", \"Z3\", \"Z4\", \"Z5\")\ndf <- data.frame(\n  zone    = factor(zones, levels = zones),\n  minutes = c(8, 22, 15, 12, 3),\n  hr_low  = c(100, 120, 140, 155, 170),\n  hr_high = c(119, 139, 154, 169, 185)\n)\n# Intensity alpha: de-emphasise low zones, fully saturate high zones\ndf$intensity <- c(0.55, 0.70, 0.82, 0.92, 1.00)\ndf$bar_label <- paste0(df$minutes, \" min\")\n\n# x-axis labels: zone code + name + bpm range\nzone_names <- c(\"Recovery\", \"Endurance\", \"Aerobic\", \"Threshold\", \"Maximum\")\nx_labels <- setNames(\n  paste0(zones, \" – \", zone_names, \"\\n\", df$hr_low, \"–\", df$hr_high, \" bpm\"),\n  zones\n)\n\n# Plot\np <- ggplot(df, aes(x = zone, y = minutes, fill = zone, alpha = I(intensity))) +\n  geom_col(width = 0.62) +\n  geom_text(\n    aes(label = bar_label, y = minutes),\n    vjust    = -0.6,\n    color    = INK,\n    size     = 3.5,\n    fontface = \"bold\"\n  ) +\n  scale_fill_manual(values = ZONE_COLORS, guide = \"none\") +\n  scale_x_discrete(labels = x_labels) +\n  scale_y_continuous(\n    expand = expansion(mult = c(0, 0.20)),\n    labels = function(x) paste0(x, \" min\"),\n    breaks = seq(0, 25, by = 5)\n  ) +\n  labs(\n    title = \"60-Minute Tempo Run · bar-heart-rate-zones · r · ggplot2 · anyplot.ai\",\n    x     = NULL,\n    y     = \"Time (minutes)\"\n  ) +\n  theme_minimal(base_size = 8) +\n  theme(\n    plot.background    = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background   = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major.x = element_blank(),\n    panel.grid.minor.x = element_blank(),\n    panel.grid.major.y = element_line(color = GRID_COLOR, linewidth = 0.3),\n    panel.grid.minor.y = element_blank(),\n    axis.title.y       = element_text(color = INK, size = 10),\n    axis.text.x        = element_text(color = INK_SOFT, size = 7.5, lineheight = 1.3),\n    axis.text.y        = element_text(color = INK_SOFT, size = 8),\n    axis.ticks         = element_blank(),\n    plot.title         = element_text(color = INK, size = 12, margin = margin(b = 12)),\n    plot.margin        = margin(16, 20, 16, 16)\n  )\n\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 8,\n  height   = 4.5,\n  units    = \"in\",\n  dpi      = 400\n)\n"}