{"spec_id":"bullet-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nbullet-basic: Basic Bullet Chart\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 88/100 | Updated: 2026-05-29\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nfrom matplotlib.lines import Line2D\nfrom matplotlib.patches import FancyBboxPatch, Patch\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n\n# Theme-adaptive chrome — Imprint palette\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\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 palette — semantic: green = above target (good/pass), red = below target (bad/fail)\nCOLOR_ABOVE = \"#009E73\"  # Imprint brand green\nCOLOR_BELOW = \"#AE3030\"  # Imprint matte red\n\n# Qualitative range band shading — neutral grayscale, theme-adaptive\nif THEME == \"light\":\n    band_colors = [\"#dcdcdc\", \"#b8b8b8\", \"#949494\"]  # lighter = poor, darker = good\nelse:\n    band_colors = [\"#2C2C29\", \"#3A3A37\", \"#484845\"]  # slightly lighter than bg = poor -> good\n\n# Data: Quarterly KPI dashboard with percentage-based metrics\nmetrics = [\n    {\"label\": \"Revenue\", \"actual\": 92, \"target\": 85, \"ranges\": [40, 70, 100]},\n    {\"label\": \"Profit Margin\", \"actual\": 38, \"target\": 45, \"ranges\": [20, 40, 60]},\n    {\"label\": \"Customer Growth\", \"actual\": 71, \"target\": 80, \"ranges\": [30, 60, 100]},\n    {\"label\": \"Satisfaction\", \"actual\": 84, \"target\": 90, \"ranges\": [50, 75, 100]},\n    {\"label\": \"On-Time Delivery\", \"actual\": 96, \"target\": 95, \"ranges\": [60, 80, 100]},\n]\n\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nbar_height = 0.32\nband_height = bar_height * 2.4\nspacing = 1.2\ny_positions = [i * spacing for i in range(len(metrics))]\n\nfor i, metric in enumerate(metrics):\n    y = y_positions[i]\n    ranges = metric[\"ranges\"]\n\n    # Qualitative range bands with rounded corners\n    band_starts = [0] + ranges[:-1]\n    for j, (start, end) in enumerate(zip(band_starts, ranges, strict=True)):\n        width = end - start\n        box = FancyBboxPatch(\n            (start, y - band_height / 2),\n            width,\n            band_height,\n            boxstyle=\"round,pad=0,rounding_size=0.08\",\n            facecolor=band_colors[j],\n            edgecolor=\"none\",\n            zorder=1,\n        )\n        ax.add_patch(box)\n\n    above_target = metric[\"actual\"] >= metric[\"target\"]\n    bar_color = COLOR_ABOVE if above_target else COLOR_BELOW\n\n    # Actual value bar with rounded corners; hatch on above-target bars = redundant CVD-safe encoding\n    actual_bar = FancyBboxPatch(\n        (0, y - bar_height / 2),\n        metric[\"actual\"],\n        bar_height,\n        boxstyle=\"round,pad=0,rounding_size=0.06\",\n        facecolor=bar_color,\n        edgecolor=INK if above_target else \"none\",\n        linewidth=0.6,\n        hatch=\"///\" if above_target else None,\n        zorder=2,\n    )\n    ax.add_patch(actual_bar)\n\n    # Target marker: thin vertical line perpendicular to bar\n    ax.vlines(\n        metric[\"target\"], y - band_height / 2 * 0.85, y + band_height / 2 * 0.85, colors=INK, linewidth=2.0, zorder=3\n    )\n\n    # Value label to the right of the max range\n    ax.text(\n        ranges[-1] + 2,\n        y,\n        f\"{metric['actual']}%\",\n        va=\"center\",\n        ha=\"left\",\n        fontsize=8,\n        fontweight=\"bold\",\n        color=bar_color,\n        zorder=4,\n    )\n\n# Y-axis: metric name labels\nax.set_yticks(y_positions)\nax.set_yticklabels([m[\"label\"] for m in metrics], fontsize=8, fontweight=\"bold\")\nax.tick_params(axis=\"y\", length=0, colors=INK_SOFT, labelcolor=INK_SOFT)\n\n# X-axis\nax.set_xlabel(\"Performance (%)\", fontsize=10, color=INK)\nax.tick_params(axis=\"x\", labelsize=8, colors=INK_SOFT, labelcolor=INK_SOFT, length=0)\n\n# Title — language token required\ntitle = \"bullet-basic · python · matplotlib · anyplot.ai\"\ntitle_len = len(title)\ntitle_fontsize = max(8, round(12 * 67 / title_len)) if title_len > 67 else 12\nax.set_title(title, fontsize=title_fontsize, fontweight=\"medium\", pad=12, color=INK)\n\n# Subtle x-axis grid\nax.xaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK, zorder=0)\nax.set_axisbelow(True)\n\n# Spines — keep bottom only for clean look\nfor spine in [\"top\", \"right\", \"left\"]:\n    ax.spines[spine].set_visible(False)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Axis limits\nax.set_xlim(left=0, right=115)\nax.set_ylim(-spacing * 0.5, y_positions[-1] + spacing * 0.5)\nax.invert_yaxis()\n\n# Legend\nlegend_elements = [\n    Patch(facecolor=COLOR_ABOVE, edgecolor=INK, linewidth=0.6, hatch=\"///\", label=\"Above Target\"),\n    Patch(facecolor=COLOR_BELOW, edgecolor=\"none\", label=\"Below Target\"),\n    Line2D([0], [0], color=INK, linewidth=2.0, label=\"Target\"),\n    Patch(facecolor=band_colors[2], edgecolor=INK_SOFT, linewidth=0.5, label=\"Good\"),\n    Patch(facecolor=band_colors[1], edgecolor=INK_SOFT, linewidth=0.5, label=\"Satisfactory\"),\n    Patch(facecolor=band_colors[0], edgecolor=INK_SOFT, linewidth=0.5, label=\"Poor\"),\n]\nleg = ax.legend(\n    handles=legend_elements, loc=\"upper center\", bbox_to_anchor=(0.5, -0.14), ncol=6, fontsize=8, frameon=True\n)\nleg.get_frame().set_facecolor(ELEVATED_BG)\nleg.get_frame().set_edgecolor(INK_SOFT)\nplt.setp(leg.get_texts(), color=INK_SOFT)\n\n# Explicit padding — do NOT use bbox_inches=\"tight\" on savefig (trims canvas)\nfig.subplots_adjust(left=0.18, right=0.93, top=0.91, bottom=0.26)\nplt.savefig(f\"plot-{THEME}.png\", dpi=400)\n"}