{"spec_id":"funnel-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nfunnel-basic: Basic Funnel Chart\nLibrary: matplotlib 3.10.9 | Python 3.14.4\nQuality: 86/100 | Updated: 2026-04-26\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n\n# Theme tokens\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\"\n\n# Okabe-Ito palette — first stage is brand green (#009E73)\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\"]\n# Light orange #AE3030 needs dark text; pick INK so the label also\n# stays legible where it overflows the narrow bottom segment.\nTEXT_ON_FILL = [\"white\", \"white\", \"white\", \"white\", INK]\n\n# Data — sales funnel example from specification\nstages = [\"Awareness\", \"Interest\", \"Consideration\", \"Intent\", \"Purchase\"]\nvalues = np.array([1000, 600, 400, 200, 100])\n\n# Geometry: widths proportional to first stage value, equal-height segments\nmax_value = values[0]\nwidths = values / max_value\nn = len(stages)\ny_edges = np.linspace(n, 0, n + 1)\ngap = 0.06\n\n# Plot\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nfor i in range(n):\n    y_top = y_edges[i] - gap / 2\n    y_bot = y_edges[i + 1] + gap / 2\n    w_top = widths[i]\n    # Flat bottom on the last segment — trapezoid ends at the actual\n    # data width instead of tapering to a decorative point.\n    w_bot = widths[i + 1] if i + 1 < n else widths[i]\n\n    y = np.array([y_top, y_bot])\n    x_left = np.array([-w_top / 2, -w_bot / 2])\n    x_right = np.array([w_top / 2, w_bot / 2])\n    ax.fill_betweenx(y, x_left, x_right, facecolor=IMPRINT[i], edgecolor=PAGE_BG, linewidth=2)\n\n    y_mid = (y_top + y_bot) / 2\n    pct = (values[i] / max_value) * 100\n    ax.text(\n        0,\n        y_mid,\n        f\"{stages[i]}\\n{values[i]:,}  ·  {pct:.0f}%\",\n        ha=\"center\",\n        va=\"center\",\n        fontsize=18,\n        fontweight=\"bold\",\n        color=TEXT_ON_FILL[i],\n    )\n\n# Style\nax.set_xlim(-0.65, 0.65)\nax.set_ylim(-0.2, n + 0.2)\nax.set_aspect(\"auto\")\nax.axis(\"off\")\nax.set_title(\"funnel-basic · matplotlib · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK, pad=20)\n\n# Stage index axis on the left\nfor i in range(n):\n    y_mid = (y_edges[i] + y_edges[i + 1]) / 2\n    ax.text(-0.62, y_mid, f\"Stage {i + 1}\", ha=\"left\", va=\"center\", fontsize=14, color=INK_SOFT)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}