{"spec_id":"bar-grouped","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nbar-grouped: Grouped Bar Chart\nLibrary: pygal 3.1.3 | Python 3.13.14\nQuality: 91/100 | Updated: 2026-08-05\n\"\"\"\n\nimport os\n\nimport pygal\nfrom pygal.style import Style\n\n\n# Theme tokens (see prompts/default-style-guide.md \"Background\" + \"Theme-adaptive Chrome\")\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint categorical palette — first series is always brand green\nIMPRINT_PALETTE = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\")\n\n# Data: Quarterly recurring revenue by subscription tier ($M) — Enterprise\n# growth outpaces the other tiers, telling a clear adoption story through the\n# data itself rather than through added annotations.\nquarters = [\"Q1\", \"Q2\", \"Q3\", \"Q4\"]\ntiers = {\"Starter\": [1.8, 1.9, 2.0, 2.1], \"Professional\": [2.4, 2.9, 3.6, 4.4], \"Enterprise\": [1.2, 1.9, 2.8, 4.1]}\n\n# Style — theme-adaptive chrome, Imprint palette, sizing tuned for 3200x1800\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT_PALETTE,\n    # pygal auto-picks black/white per-bar for print_values based on bar\n    # fill lightness, ignoring the theme — force the theme ink color so\n    # value labels (drawn above the bar, on the page background) stay\n    # legible on both surfaces.\n    value_colors=(INK,) * len(tiers),\n    # pygal's graph.css ships guide_stroke_color=\"black\" and layers it over\n    # style.css's foreground_subtle rule for the same selector, so gridlines\n    # render pure black regardless of theme unless overridden here — nearly\n    # invisible against the near-black dark-theme background.\n    guide_stroke_color=INK_MUTED,\n    major_guide_stroke_color=INK_MUTED,\n    title_font_size=66,\n    label_font_size=56,\n    major_label_font_size=44,\n    legend_font_size=44,\n    value_font_size=36,\n    stroke_width=2.5,\n    opacity=0.92,\n    opacity_hover=1.0,\n)\n\n# Chart — grouped bars, y-axis grid only, bottom legend to keep the plot area\n# uncluttered. Explicit y_labels (with all of them forced major via\n# y_labels_major_count) give the axis a real scale — pygal's auto-picked\n# major labels can otherwise collapse to just \"$0.0M\" at the origin.\nchart = pygal.Bar(\n    width=3200,\n    height=1800,\n    style=custom_style,\n    title=\"bar-grouped · python · pygal · anyplot.ai\",\n    x_title=\"Quarter\",\n    y_title=\"Quarterly Revenue ($M)\",\n    show_x_guides=False,\n    show_y_guides=True,\n    y_labels=[0, 1, 2, 3, 4, 5],\n    y_labels_major_count=6,\n    legend_at_bottom=True,\n    legend_at_bottom_columns=3,\n    legend_box_size=32,\n    margin=60,\n    spacing=50,\n    print_values=True,\n    print_values_position=\"top\",\n    value_formatter=lambda x: f\"${x:.1f}M\",\n    tooltip_border_radius=10,\n)\nchart.x_labels = quarters\n\nfor tier, revenue in tiers.items():\n    chart.add(tier, revenue)\n\n# Save\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}