{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "758e4c36",
   "metadata": {},
   "source": [
    "# CTM Token Calculator — Genesys AI Cost & Business Case\n",
    "\n",
    "**Version 0.1.0** · interactive working analysis for Robert / CTM stakeholders / NTT delivery.\n",
    "\n",
    "Models Genesys Cloud **CX 3** platform + AI feature costs (published token meters,\n",
    "confidence-flagged) against pressure-tested benefit scenarios — replacing single-point\n",
    "vendor ROI outputs with **Floor / Realistic / Stretch** sensitivity-aware analysis.\n",
    "\n",
    "> ⚠️ **Planning tool.** List rates unless overridden; not contractual pricing.\n",
    "> Site data outside NAM is **estimated — confirm with CTM**.\n",
    "\n",
    "Same `tokencalc` library as the Streamlit app (`streamlit run app/streamlit_app.py`) —\n",
    "Run-All here produces identical headline numbers on default inputs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "57efb206",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tokencalc loaded — 9 sites, 2,088 named users (contracted: 2,088)\n"
     ]
    }
   ],
   "source": [
    "# ── Setup ──────────────────────────────────────────────────────────\n",
    "import sys, pathlib\n",
    "_ROOT = pathlib.Path.cwd()\n",
    "if not (_ROOT / \"tokencalc\").exists():           # notebook lives in notebooks/\n",
    "    _ROOT = _ROOT.parent\n",
    "sys.path.insert(0, str(_ROOT))\n",
    "\n",
    "import dataclasses\n",
    "import pandas as pd\n",
    "import plotly.express as px\n",
    "import plotly.graph_objects as go\n",
    "\n",
    "from tokencalc import *\n",
    "from tokencalc.scenarios import BENEFIT_PARAMS\n",
    "\n",
    "pd.options.display.float_format = \"{:,.0f}\".format\n",
    "print(f\"tokencalc loaded — {len(CTM_DEFAULT_SITES)} sites, \"\n",
    "      f\"{sum(s.named_users for s in CTM_DEFAULT_SITES):,} named users \"\n",
    "      f\"(contracted: {CONTRACTED_NAMED_USERS:,})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbf6851d",
   "metadata": {},
   "source": [
    "## Inputs\n",
    "\n",
    "Sites, cost takeouts, and feature scoping as Python objects (CTM defaults).\n",
    "To resume a saved scenario instead:\n",
    "`sites, takeouts, scopes = scenario_state_from_json(\"my_scenario.json\")`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "361bde24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>site_name</th>\n",
       "      <th>region_pricing</th>\n",
       "      <th>agents</th>\n",
       "      <th>supervisors</th>\n",
       "      <th>voice_volume_monthly</th>\n",
       "      <th>email_volume_monthly</th>\n",
       "      <th>chat_volume_monthly</th>\n",
       "      <th>sms_volume_monthly</th>\n",
       "      <th>voice_aht_seconds</th>\n",
       "      <th>email_aht_seconds</th>\n",
       "      <th>chat_aht_seconds</th>\n",
       "      <th>voice_acw_seconds</th>\n",
       "      <th>fully_loaded_agent_cost_annual</th>\n",
       "      <th>fully_loaded_supervisor_cost_annual</th>\n",
       "      <th>licence_type</th>\n",
       "      <th>languages</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>NAM</td>\n",
       "      <td>US</td>\n",
       "      <td>890</td>\n",
       "      <td>60</td>\n",
       "      <td>1214358</td>\n",
       "      <td>275800</td>\n",
       "      <td>110</td>\n",
       "      <td>1040</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>65000</td>\n",
       "      <td>95000</td>\n",
       "      <td>named</td>\n",
       "      <td>English, French, Spanish</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>EMEA</td>\n",
       "      <td>EU</td>\n",
       "      <td>320</td>\n",
       "      <td>25</td>\n",
       "      <td>420000</td>\n",
       "      <td>95000</td>\n",
       "      <td>40</td>\n",
       "      <td>400</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>60000</td>\n",
       "      <td>88000</td>\n",
       "      <td>named</td>\n",
       "      <td>English, French, German, Italian, Spanish</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>AUZ</td>\n",
       "      <td>AU</td>\n",
       "      <td>180</td>\n",
       "      <td>15</td>\n",
       "      <td>250000</td>\n",
       "      <td>56000</td>\n",
       "      <td>25</td>\n",
       "      <td>250</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>70000</td>\n",
       "      <td>100000</td>\n",
       "      <td>named</td>\n",
       "      <td>English</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>APAC HK</td>\n",
       "      <td>APAC</td>\n",
       "      <td>120</td>\n",
       "      <td>10</td>\n",
       "      <td>160000</td>\n",
       "      <td>38000</td>\n",
       "      <td>15</td>\n",
       "      <td>150</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>55000</td>\n",
       "      <td>80000</td>\n",
       "      <td>named</td>\n",
       "      <td>English, Cantonese, Mandarin</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>APAC SG</td>\n",
       "      <td>APAC</td>\n",
       "      <td>110</td>\n",
       "      <td>10</td>\n",
       "      <td>150000</td>\n",
       "      <td>34000</td>\n",
       "      <td>15</td>\n",
       "      <td>120</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>55000</td>\n",
       "      <td>80000</td>\n",
       "      <td>named</td>\n",
       "      <td>English, Mandarin, Malay</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>APAC SH</td>\n",
       "      <td>APAC</td>\n",
       "      <td>130</td>\n",
       "      <td>10</td>\n",
       "      <td>175000</td>\n",
       "      <td>40000</td>\n",
       "      <td>15</td>\n",
       "      <td>130</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>35000</td>\n",
       "      <td>55000</td>\n",
       "      <td>named</td>\n",
       "      <td>Mandarin</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>APAC GZ</td>\n",
       "      <td>APAC</td>\n",
       "      <td>90</td>\n",
       "      <td>8</td>\n",
       "      <td>120000</td>\n",
       "      <td>28000</td>\n",
       "      <td>10</td>\n",
       "      <td>100</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>35000</td>\n",
       "      <td>55000</td>\n",
       "      <td>named</td>\n",
       "      <td>Mandarin, Cantonese</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>APAC JP</td>\n",
       "      <td>APAC</td>\n",
       "      <td>60</td>\n",
       "      <td>6</td>\n",
       "      <td>80000</td>\n",
       "      <td>19000</td>\n",
       "      <td>8</td>\n",
       "      <td>80</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>60000</td>\n",
       "      <td>85000</td>\n",
       "      <td>named</td>\n",
       "      <td>Japanese</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>APAC TW</td>\n",
       "      <td>APAC</td>\n",
       "      <td>40</td>\n",
       "      <td>4</td>\n",
       "      <td>54000</td>\n",
       "      <td>12000</td>\n",
       "      <td>5</td>\n",
       "      <td>50</td>\n",
       "      <td>300</td>\n",
       "      <td>600</td>\n",
       "      <td>480</td>\n",
       "      <td>60</td>\n",
       "      <td>40000</td>\n",
       "      <td>60000</td>\n",
       "      <td>named</td>\n",
       "      <td>Mandarin</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  site_name region_pricing  agents  supervisors  voice_volume_monthly  \\\n",
       "0       NAM             US     890           60               1214358   \n",
       "1      EMEA             EU     320           25                420000   \n",
       "2       AUZ             AU     180           15                250000   \n",
       "3   APAC HK           APAC     120           10                160000   \n",
       "4   APAC SG           APAC     110           10                150000   \n",
       "5   APAC SH           APAC     130           10                175000   \n",
       "6   APAC GZ           APAC      90            8                120000   \n",
       "7   APAC JP           APAC      60            6                 80000   \n",
       "8   APAC TW           APAC      40            4                 54000   \n",
       "\n",
       "   email_volume_monthly  chat_volume_monthly  sms_volume_monthly  \\\n",
       "0                275800                  110                1040   \n",
       "1                 95000                   40                 400   \n",
       "2                 56000                   25                 250   \n",
       "3                 38000                   15                 150   \n",
       "4                 34000                   15                 120   \n",
       "5                 40000                   15                 130   \n",
       "6                 28000                   10                 100   \n",
       "7                 19000                    8                  80   \n",
       "8                 12000                    5                  50   \n",
       "\n",
       "   voice_aht_seconds  email_aht_seconds  chat_aht_seconds  voice_acw_seconds  \\\n",
       "0                300                600               480                 60   \n",
       "1                300                600               480                 60   \n",
       "2                300                600               480                 60   \n",
       "3                300                600               480                 60   \n",
       "4                300                600               480                 60   \n",
       "5                300                600               480                 60   \n",
       "6                300                600               480                 60   \n",
       "7                300                600               480                 60   \n",
       "8                300                600               480                 60   \n",
       "\n",
       "   fully_loaded_agent_cost_annual  fully_loaded_supervisor_cost_annual  \\\n",
       "0                           65000                                95000   \n",
       "1                           60000                                88000   \n",
       "2                           70000                               100000   \n",
       "3                           55000                                80000   \n",
       "4                           55000                                80000   \n",
       "5                           35000                                55000   \n",
       "6                           35000                                55000   \n",
       "7                           60000                                85000   \n",
       "8                           40000                                60000   \n",
       "\n",
       "  licence_type                                  languages  \n",
       "0        named                   English, French, Spanish  \n",
       "1        named  English, French, German, Italian, Spanish  \n",
       "2        named                                    English  \n",
       "3        named               English, Cantonese, Mandarin  \n",
       "4        named                   English, Mandarin, Malay  \n",
       "5        named                                   Mandarin  \n",
       "6        named                        Mandarin, Cantonese  \n",
       "7        named                                   Japanese  \n",
       "8        named                                   Mandarin  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>takeout</th>\n",
       "      <th>annual_cost</th>\n",
       "      <th>start_year</th>\n",
       "      <th>confidence</th>\n",
       "      <th>notes</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>NICE IEX (NAM)</td>\n",
       "      <td>1300000</td>\n",
       "      <td>1</td>\n",
       "      <td>🟡 estimated</td>\n",
       "      <td>Mid-band estimate; needs CTM contract confirma...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Legacy CC platform</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>🔴 unknown</td>\n",
       "      <td>Placeholder — populate once retirement scope i...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              takeout  annual_cost  start_year   confidence  \\\n",
       "0      NICE IEX (NAM)      1300000           1  🟡 estimated   \n",
       "1  Legacy CC platform            0           2    🔴 unknown   \n",
       "\n",
       "                                               notes  \n",
       "0  Mid-band estimate; needs CTM contract confirma...  \n",
       "1  Placeholder — populate once retirement scope i...  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sites = list(CTM_DEFAULT_SITES)\n",
    "takeouts = list(CTM_DEFAULT_TAKEOUTS)\n",
    "scopes = list(CTM_DEFAULT_FEATURE_SCOPES)\n",
    "meters = dict(DEFAULT_METERS)\n",
    "pricing = dict(DEFAULT_PRICING)\n",
    "\n",
    "total_users = sum(s.named_users for s in sites)\n",
    "if total_users != CONTRACTED_NAMED_USERS:\n",
    "    print(f\"⚠️ Named users ({total_users:,}) ≠ contracted licences \"\n",
    "          f\"({CONTRACTED_NAMED_USERS:,})\")\n",
    "\n",
    "display(sites_dataframe(sites))\n",
    "display(pd.DataFrame([{\"takeout\": t.name, \"annual_cost\": t.annual_cost,\n",
    "                       \"start_year\": t.start_year,\n",
    "                       \"confidence\": t.confidence.icon + \" \" + t.confidence.value,\n",
    "                       \"notes\": t.notes} for t in takeouts]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51e84f75",
   "metadata": {},
   "source": [
    "## Token meters\n",
    "\n",
    "Source: [Genesys Cloud AI Experience metering details](https://help.genesys.cloud/articles/genesys-cloud-tokens-model/) (2026-06-07)\n",
    "\n",
    "🟢 confirmed (published Genesys rate) · 🟡 estimated · 🔴 unknown (working default, rate not yet published).\n",
    "\n",
    "**Licence variants** — Agent Copilot and Speech & Text Analytics each have two published rates:\n",
    "- **[named]** — 40 tok/user/month (Copilot) · 30 tok/user/month (STA)\n",
    "- **[concurrent]** — 60 tok/user/month (Copilot) · 45 tok/user/month (STA)\n",
    "\n",
    "CTM has **named** licences; the `[named]` variants are used in `CTM_DEFAULT_FEATURE_SCOPES`.\n",
    "Override by swapping the feature name in `scopes` for sites with concurrent licences.\n",
    "\n",
    "**Copilot rule:** Agent Copilot includes interaction summarization, so\n",
    "AI Summary & Insights is never billed at Copilot-enabled sites.\n",
    "\n",
    "**New in 2026-06-07 catalogue:** Digital Bot (51 sessions/token), AI Scoring\n",
    "(20 evaluations/token), Predictive Routing (17 routes/token), Genesys Cloud Copilot\n",
    "(20 AI actions/token), and AI Translate is now a confirmed consumption meter\n",
    "(2 translations/token, previously UNKNOWN)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "72311955",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>feature</th>\n",
       "      <th>meter_type</th>\n",
       "      <th>units_per_token</th>\n",
       "      <th>tokens_per_unit</th>\n",
       "      <th>confidence</th>\n",
       "      <th>notes</th>\n",
       "      <th>source</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Voice Bot</td>\n",
       "      <td>per_minute</td>\n",
       "      <td>17</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>IVR self-service voice bot minutes; 17 min per...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Digital Bot</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>51</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Digital (non-voice) bot sessions; 51 sessions ...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Virtual Agent (legacy)</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Legacy (non-agentic) virtual agent; 0.5 tokens...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Agentic Virtual Agent</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Agentic VA; 1.2 tokens per interaction.</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Agent Copilot [named]</td>\n",
       "      <td>per_user_per_month</td>\n",
       "      <td>NaN</td>\n",
       "      <td>40</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>40 tokens per named user per month. Includes i...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Agent Copilot [concurrent]</td>\n",
       "      <td>per_user_per_month</td>\n",
       "      <td>NaN</td>\n",
       "      <td>60</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>60 tokens per concurrent user per month. Inclu...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>AI Scoring</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>20</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>AI-scored quality evaluations; 20 evaluations ...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>AI Summary &amp; Insights</td>\n",
       "      <td>per_summary</td>\n",
       "      <td>50</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Supervisor standalone summarization; 50 summar...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Speech &amp; Text Analytics [named]</td>\n",
       "      <td>per_user_per_month</td>\n",
       "      <td>NaN</td>\n",
       "      <td>30</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>STA named licence; 30 tokens per named user pe...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>Speech &amp; Text Analytics [concurrent]</td>\n",
       "      <td>per_user_per_month</td>\n",
       "      <td>NaN</td>\n",
       "      <td>45</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>STA concurrent licence; 45 tokens per concurre...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>Predictive Routing</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>17</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Predictive routing; 17 routes per token.</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>Direct Messaging</td>\n",
       "      <td>per_message</td>\n",
       "      <td>400</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Apple Messages for Business, Facebook Messenge...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>Social Listening</td>\n",
       "      <td>per_message</td>\n",
       "      <td>400</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Genesys Cloud Social; 400 social post ingestio...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>Social Responses</td>\n",
       "      <td>per_message</td>\n",
       "      <td>400</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>Social Post Responses; 400 outbound messages p...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>AI Translate</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>AI translation; 2 translations per token.</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>Genesys Cloud Copilot</td>\n",
       "      <td>per_interaction</td>\n",
       "      <td>20</td>\n",
       "      <td>0</td>\n",
       "      <td>🟢 confirmed</td>\n",
       "      <td>20 AI actions per token; Genesys Cloud knowled...</td>\n",
       "      <td>https://help.genesys.cloud/articles/genesys-cl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>Email AI (Auto-Suggest)</td>\n",
       "      <td>per_user_per_month</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>🔴 unknown</td>\n",
       "      <td>Requires Agent Copilot. Token rate not yet pub...</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>Email AI (Auto-Respond)</td>\n",
       "      <td>per_message</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>🔴 unknown</td>\n",
       "      <td>Feature not yet available; rate TBD.</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                 feature          meter_type  units_per_token  \\\n",
       "0                              Voice Bot          per_minute               17   \n",
       "1                            Digital Bot     per_interaction               51   \n",
       "2                 Virtual Agent (legacy)     per_interaction                2   \n",
       "3                  Agentic Virtual Agent     per_interaction                1   \n",
       "4                  Agent Copilot [named]  per_user_per_month              NaN   \n",
       "5             Agent Copilot [concurrent]  per_user_per_month              NaN   \n",
       "6                             AI Scoring     per_interaction               20   \n",
       "7                  AI Summary & Insights         per_summary               50   \n",
       "8        Speech & Text Analytics [named]  per_user_per_month              NaN   \n",
       "9   Speech & Text Analytics [concurrent]  per_user_per_month              NaN   \n",
       "10                    Predictive Routing     per_interaction               17   \n",
       "11                      Direct Messaging         per_message              400   \n",
       "12                      Social Listening         per_message              400   \n",
       "13                      Social Responses         per_message              400   \n",
       "14                          AI Translate     per_interaction                2   \n",
       "15                 Genesys Cloud Copilot     per_interaction               20   \n",
       "16               Email AI (Auto-Suggest)  per_user_per_month              NaN   \n",
       "17               Email AI (Auto-Respond)         per_message              NaN   \n",
       "\n",
       "    tokens_per_unit   confidence  \\\n",
       "0                 0  🟢 confirmed   \n",
       "1                 0  🟢 confirmed   \n",
       "2                 0  🟢 confirmed   \n",
       "3                 1  🟢 confirmed   \n",
       "4                40  🟢 confirmed   \n",
       "5                60  🟢 confirmed   \n",
       "6                 0  🟢 confirmed   \n",
       "7                 0  🟢 confirmed   \n",
       "8                30  🟢 confirmed   \n",
       "9                45  🟢 confirmed   \n",
       "10                0  🟢 confirmed   \n",
       "11                0  🟢 confirmed   \n",
       "12                0  🟢 confirmed   \n",
       "13                0  🟢 confirmed   \n",
       "14                0  🟢 confirmed   \n",
       "15                0  🟢 confirmed   \n",
       "16                0    🔴 unknown   \n",
       "17                0    🔴 unknown   \n",
       "\n",
       "                                                notes  \\\n",
       "0   IVR self-service voice bot minutes; 17 min per...   \n",
       "1   Digital (non-voice) bot sessions; 51 sessions ...   \n",
       "2   Legacy (non-agentic) virtual agent; 0.5 tokens...   \n",
       "3             Agentic VA; 1.2 tokens per interaction.   \n",
       "4   40 tokens per named user per month. Includes i...   \n",
       "5   60 tokens per concurrent user per month. Inclu...   \n",
       "6   AI-scored quality evaluations; 20 evaluations ...   \n",
       "7   Supervisor standalone summarization; 50 summar...   \n",
       "8   STA named licence; 30 tokens per named user pe...   \n",
       "9   STA concurrent licence; 45 tokens per concurre...   \n",
       "10           Predictive routing; 17 routes per token.   \n",
       "11  Apple Messages for Business, Facebook Messenge...   \n",
       "12  Genesys Cloud Social; 400 social post ingestio...   \n",
       "13  Social Post Responses; 400 outbound messages p...   \n",
       "14          AI translation; 2 translations per token.   \n",
       "15  20 AI actions per token; Genesys Cloud knowled...   \n",
       "16  Requires Agent Copilot. Token rate not yet pub...   \n",
       "17               Feature not yet available; rate TBD.   \n",
       "\n",
       "                                               source  \n",
       "0   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "1   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "2   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "3   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "4   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "5   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "6   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "7   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "8   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "9   https://help.genesys.cloud/articles/genesys-cl...  \n",
       "10  https://help.genesys.cloud/articles/genesys-cl...  \n",
       "11  https://help.genesys.cloud/articles/genesys-cl...  \n",
       "12  https://help.genesys.cloud/articles/genesys-cl...  \n",
       "13  https://help.genesys.cloud/articles/genesys-cl...  \n",
       "14  https://help.genesys.cloud/articles/genesys-cl...  \n",
       "15  https://help.genesys.cloud/articles/genesys-cl...  \n",
       "16                                                     \n",
       "17                                                     "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display(meters_dataframe(meters))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c308d2f",
   "metadata": {},
   "source": [
    "## Controls\n",
    "\n",
    "Plain variables (always work). Run the optional widget cell below for sliders —\n",
    "either way, re-run the calculation cells after changing anything."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8b24676f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Scenario: realistic · Year 1 · benefit params: realistic\n"
     ]
    }
   ],
   "source": [
    "SCENARIO = \"realistic\"     # \"floor\" | \"realistic\" | \"stretch\"\n",
    "YEAR = 1                   # 1 | 2 | 3\n",
    "BENEFIT_PARAMS_MODE = \"realistic\"   # \"realistic\" (pressure-tested) | \"claim\" (Genesys)\n",
    "USE_CONTRACTED_RATES = False\n",
    "IMPLEMENTATION_COST = 0.0   # one-off, amortized over 3 years\n",
    "\n",
    "scenario = get_scenario(SCENARIO)\n",
    "print(f\"Scenario: {SCENARIO} · Year {YEAR} · benefit params: {BENEFIT_PARAMS_MODE}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "810e9dae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "eff7ea970d66430abeb6bfa7d4774f78",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "ToggleButtons(description='Scenario', index=1, options=('floor', 'realistic', 'stretch'), value='realistic')"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9f99dcb8205740ae86cbaeb7d313da80",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "ToggleButtons(description='Year', options=(1, 2, 3), value=1)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Optional: ipywidgets controls (skip if ipywidgets unavailable)\n",
    "try:\n",
    "    import ipywidgets as W\n",
    "    from IPython.display import display as _disp\n",
    "\n",
    "    _scen = W.ToggleButtons(options=[\"floor\", \"realistic\", \"stretch\"],\n",
    "                            value=SCENARIO, description=\"Scenario\")\n",
    "    _year = W.ToggleButtons(options=[1, 2, 3], value=YEAR, description=\"Year\")\n",
    "\n",
    "    def _on_change(change):\n",
    "        global SCENARIO, YEAR, scenario\n",
    "        SCENARIO, YEAR = _scen.value, _year.value\n",
    "        scenario = get_scenario(SCENARIO)\n",
    "        print(f\"→ {SCENARIO}, year {YEAR} — re-run the cells below.\")\n",
    "\n",
    "    _scen.observe(_on_change, \"value\"); _year.observe(_on_change, \"value\")\n",
    "    _disp(_scen, _year)\n",
    "except ImportError:\n",
    "    print(\"ipywidgets not installed — use the plain variables above.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a590988",
   "metadata": {},
   "source": [
    "## Virtual Agents — deflection, costs & benefits\n",
    "\n",
    "**Both** voice volume cost drivers (token consumption) **and** benefit drivers\n",
    "(agent labour avoided). Two mechanisms operate on the same call pool:\n",
    "\n",
    "| Layer | What it does | Cost meter | Benefit |\n",
    "|---|---|---|---|\n",
    "| **Voice Bot** | IVR self-service on the full call pool | per-minute (17 min/token) | labour avoided × completion |\n",
    "| **Agentic Virtual Agent** | Handles a share of the **residual** (calls the bot did not deflect) | per-interaction (1.2 tok/interaction) | labour avoided × completion |\n",
    "\n",
    "### Layered (sequential) deflection model\n",
    "\n",
    "The two mechanisms are **substitutes**, not independent additive benefits:\n",
    "\n",
    "$$\n",
    "\\text{effective deflection} = r_{bot} + (1 - r_{bot}) \\cdot r_{va}\n",
    "$$\n",
    "\n",
    "Realistic scenario: 35% + 65% × 15% = **44.75%** (not the naive 50%).\n",
    "\n",
    "### Three realization haircuts on labour avoided\n",
    "\n",
    "Deflected volume does NOT translate 1:1 into labour savings:\n",
    "\n",
    "1. **Completion rate** — share of \"deflected\" calls the bot/VA fully handles\n",
    "   without escalating mid-session (60-75% voice bot, 50-70% agentic VA Y1).\n",
    "2. **Labour realization** — staffing flexibility ceiling (minimums, shrinkage,\n",
    "   occupancy); 70-85% of deflected volume actually reduces FTE need.\n",
    "3. **Callback discount** — poorly-handled deflections drive 5-10% repeat contacts.\n",
    "\n",
    "Combined realistic factor: 0.70 × 0.80 × (1 − 0.05) ≈ **0.53**\n",
    "\n",
    "So a naive \"$25M of labour avoided\" is realistically ~$13M. The variables below\n",
    "override the scenario defaults — adjust them to test sensitivity, then re-run\n",
    "the Cost & Benefit cells.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "65773422",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Voice Bot: 35% of full pool · Agentic VA: 15% of residual\n",
      "Effective deflection: 44.75%  ·  Realization factor: 53.2%  ·  Net labour avoidance: 23.8%\n"
     ]
    }
   ],
   "source": [
    "# ── Virtual Agent inputs (override scenario defaults below) ──────────\n",
    "# Cost & benefit drivers — applied as deflection_target overrides on the\n",
    "# Voice Bot and Agentic VA feature scopes; realization haircuts mutate\n",
    "# the scenario object so calculate_va_deflection_benefit picks them up.\n",
    "\n",
    "# Voice Bot — % of FULL voice volume deflected to the bot\n",
    "VA_BOT_DEFLECTION   = scenario.voice_bot_deflection      # cost & benefit\n",
    "VA_BOT_AVG_MINUTES  = scenario.voice_bot_avg_minutes     # cost only\n",
    "\n",
    "# Agentic VA — % of RESIDUAL (1 − bot) deflected to the agentic VA\n",
    "VA_AGENTIC_DEFLECTION = scenario.agentic_va_deflection   # cost & benefit\n",
    "\n",
    "# Realization haircuts (benefit-side only — never reduce token consumption)\n",
    "VA_COMPLETION_RATE    = scenario.va_completion_rate      # bot/VA fully handles call\n",
    "VA_LABOUR_REALIZATION = scenario.va_labour_realization   # staffing flexibility\n",
    "VA_CALLBACK_DISCOUNT  = scenario.va_callback_discount    # 5-10% repeat contacts\n",
    "\n",
    "\n",
    "def _apply_va_inputs():\n",
    "    \"\"\"Push notebook variables into the scenario + scopes used downstream.\"\"\"\n",
    "    global scopes\n",
    "    # Mutate scenario (regular dataclass, not frozen) — picked up by\n",
    "    # calculate_va_deflection_benefit via _param() and direct attribute reads.\n",
    "    scenario.voice_bot_deflection   = VA_BOT_DEFLECTION\n",
    "    scenario.voice_bot_avg_minutes  = VA_BOT_AVG_MINUTES\n",
    "    scenario.agentic_va_deflection  = VA_AGENTIC_DEFLECTION\n",
    "    scenario.va_completion_rate     = VA_COMPLETION_RATE\n",
    "    scenario.va_labour_realization  = VA_LABOUR_REALIZATION\n",
    "    scenario.va_callback_discount   = VA_CALLBACK_DISCOUNT\n",
    "    # ALSO patch BENEFIT_PARAMS so the realistic path uses our overrides\n",
    "    # (calculate_va_deflection_benefit reads via _param()).\n",
    "    BENEFIT_PARAMS[\"va_completion_rate\"][\"realistic\"]    = VA_COMPLETION_RATE\n",
    "    BENEFIT_PARAMS[\"va_labour_realization\"][\"realistic\"] = VA_LABOUR_REALIZATION\n",
    "    BENEFIT_PARAMS[\"va_callback_discount\"][\"realistic\"]  = VA_CALLBACK_DISCOUNT\n",
    "    # Override deflection_target on the Voice Bot / Agentic VA scopes\n",
    "    scopes = [\n",
    "        dataclasses.replace(\n",
    "            s,\n",
    "            deflection_target=(\n",
    "                VA_BOT_DEFLECTION       if s.feature == \"Voice Bot\"\n",
    "                else VA_AGENTIC_DEFLECTION if s.feature == \"Agentic Virtual Agent\"\n",
    "                else s.deflection_target\n",
    "            ),\n",
    "        )\n",
    "        for s in scopes\n",
    "    ]\n",
    "\n",
    "\n",
    "_apply_va_inputs()\n",
    "\n",
    "bot_pct = VA_BOT_DEFLECTION * 100\n",
    "va_pct = VA_AGENTIC_DEFLECTION * 100\n",
    "combined = VA_BOT_DEFLECTION + (1 - VA_BOT_DEFLECTION) * VA_AGENTIC_DEFLECTION\n",
    "real_factor = (\n",
    "    VA_COMPLETION_RATE * VA_LABOUR_REALIZATION * (1 - VA_CALLBACK_DISCOUNT)\n",
    ")\n",
    "print(\n",
    "    f\"Voice Bot: {bot_pct:.0f}% of full pool · \"\n",
    "    f\"Agentic VA: {va_pct:.0f}% of residual\\n\"\n",
    "    f\"Effective deflection: {combined*100:.2f}%  ·  \"\n",
    "    f\"Realization factor: {real_factor*100:.1f}%  ·  \"\n",
    "    f\"Net labour avoidance: {combined*real_factor*100:.1f}%\"\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "872af216",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "16b420088b6e40cf98654573e7887cfd",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HBox(children=(FloatSlider(value=0.35, description='Bot %', max=0.7, readout_format='.0%', step…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Optional: ipywidgets sliders for VA inputs (skip if ipywidgets unavailable)\n",
    "try:\n",
    "    import ipywidgets as W\n",
    "    from IPython.display import display as _disp\n",
    "\n",
    "    _w_bot   = W.FloatSlider(value=VA_BOT_DEFLECTION,   min=0, max=0.7,\n",
    "                             step=0.01, description=\"Bot %\",\n",
    "                             readout_format=\".0%\")\n",
    "    _w_botm  = W.FloatSlider(value=VA_BOT_AVG_MINUTES,  min=0.5, max=5.0,\n",
    "                             step=0.1, description=\"Bot min\")\n",
    "    _w_va    = W.FloatSlider(value=VA_AGENTIC_DEFLECTION, min=0, max=0.5,\n",
    "                             step=0.01, description=\"VA %\",\n",
    "                             readout_format=\".0%\")\n",
    "    _w_cmp   = W.FloatSlider(value=VA_COMPLETION_RATE,   min=0.3, max=1.0,\n",
    "                             step=0.01, description=\"Completion\",\n",
    "                             readout_format=\".0%\")\n",
    "    _w_lab   = W.FloatSlider(value=VA_LABOUR_REALIZATION, min=0.3, max=1.0,\n",
    "                             step=0.01, description=\"Labour real.\",\n",
    "                             readout_format=\".0%\")\n",
    "    _w_cb    = W.FloatSlider(value=VA_CALLBACK_DISCOUNT,  min=0.0, max=0.30,\n",
    "                             step=0.01, description=\"Callback\",\n",
    "                             readout_format=\".0%\")\n",
    "\n",
    "    def _on_va_change(change):\n",
    "        global VA_BOT_DEFLECTION, VA_BOT_AVG_MINUTES, VA_AGENTIC_DEFLECTION\n",
    "        global VA_COMPLETION_RATE, VA_LABOUR_REALIZATION, VA_CALLBACK_DISCOUNT\n",
    "        VA_BOT_DEFLECTION     = _w_bot.value\n",
    "        VA_BOT_AVG_MINUTES    = _w_botm.value\n",
    "        VA_AGENTIC_DEFLECTION = _w_va.value\n",
    "        VA_COMPLETION_RATE    = _w_cmp.value\n",
    "        VA_LABOUR_REALIZATION = _w_lab.value\n",
    "        VA_CALLBACK_DISCOUNT  = _w_cb.value\n",
    "        _apply_va_inputs()\n",
    "        eff = VA_BOT_DEFLECTION + (1-VA_BOT_DEFLECTION)*VA_AGENTIC_DEFLECTION\n",
    "        rf  = VA_COMPLETION_RATE * VA_LABOUR_REALIZATION * (1-VA_CALLBACK_DISCOUNT)\n",
    "        print(f\"→ effective {eff*100:.2f}% · realization {rf*100:.1f}% \"\n",
    "              f\"· net {eff*rf*100:.1f}% — re-run cells below.\")\n",
    "\n",
    "    for w in (_w_bot, _w_botm, _w_va, _w_cmp, _w_lab, _w_cb):\n",
    "        w.observe(_on_va_change, \"value\")\n",
    "    _disp(W.VBox([\n",
    "        W.HBox([_w_bot, _w_botm, _w_va]),\n",
    "        W.HBox([_w_cmp, _w_lab, _w_cb]),\n",
    "    ]))\n",
    "except ImportError:\n",
    "    print(\"ipywidgets not installed — adjust the variables above.\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "07ed3a9e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "decreasing": {
          "marker": {
           "color": "#C62828"
          }
         },
         "increasing": {
          "marker": {
           "color": "#2E7D32"
          }
         },
         "measure": [
          "absolute",
          "relative",
          "relative",
          "relative",
          "total"
         ],
         "name": "Call flow",
         "orientation": "v",
         "text": [
          "100%",
          "−35%",
          "−15% of residual",
          "",
          "55.2%"
         ],
         "textposition": "outside",
         "totals": {
          "marker": {
           "color": "#1565C0"
          }
         },
         "type": "waterfall",
         "x": [
          "Total calls<br>(14,572,296)",
          "Voice Bot<br>(−5,100,304)",
          "Agentic VA<br>(−1,420,799)",
          "To agent<br>(8,051,194)",
          "Net to agent"
         ],
         "y": [
          14572296,
          -5100303.6,
          -1420798.86,
          0,
          0
         ]
        }
       ],
       "layout": {
        "height": 420,
        "margin": {
         "b": 40,
         "l": 20,
         "r": 20,
         "t": 60
        },
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "NAM deflection cascade · realistic scenario · 44.8% effective deflection"
        },
        "yaxis": {
         "title": {
          "text": "Annual calls"
         }
        }
       }
      },
      "image/png": "[encoded data, 55436 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>layer</th>\n",
       "      <th>% of total</th>\n",
       "      <th>annual calls</th>\n",
       "      <th>labour avoided (raw)</th>\n",
       "      <th>labour avoided (realized)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Voice Bot deflection</td>\n",
       "      <td>35.0%</td>\n",
       "      <td>5,100,304</td>\n",
       "      <td>13,282,041</td>\n",
       "      <td>7,066,046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Agentic VA deflection (residual)</td>\n",
       "      <td>9.8%</td>\n",
       "      <td>1,420,799</td>\n",
       "      <td>3,699,997</td>\n",
       "      <td>1,968,398</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Combined (effective)</td>\n",
       "      <td>44.75%</td>\n",
       "      <td>6,521,102</td>\n",
       "      <td>16,982,038</td>\n",
       "      <td>9,034,444</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                              layer % of total  annual calls  \\\n",
       "0              Voice Bot deflection      35.0%     5,100,304   \n",
       "1  Agentic VA deflection (residual)       9.8%     1,420,799   \n",
       "2              Combined (effective)     44.75%     6,521,102   \n",
       "\n",
       "   labour avoided (raw)  labour avoided (realized)  \n",
       "0            13,282,041                  7,066,046  \n",
       "1             3,699,997                  1,968,398  \n",
       "2            16,982,038                  9,034,444  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NAM realization haircut: $16,982,038 raw → $9,034,444 realized (×0.532 = 70% completion × 80% labour × 95% retained)\n"
     ]
    }
   ],
   "source": [
    "# Visualize the deflection cascade for the largest site (NAM) at the\n",
    "# current scenario × year. Shows where calls go and how realization\n",
    "# haircuts shrink raw deflection into actual labour savings.\n",
    "\n",
    "_site = next(s for s in sites if s.site_name == \"NAM\")\n",
    "_annual_calls = _site.voice_volume_monthly * 12\n",
    "_aht_seconds  = _site.voice_aht_seconds\n",
    "_labour_rate  = _site.agent_cost_per_second\n",
    "\n",
    "bot_calls       = _annual_calls * VA_BOT_DEFLECTION\n",
    "residual_calls  = _annual_calls * (1 - VA_BOT_DEFLECTION)\n",
    "va_calls        = residual_calls * VA_AGENTIC_DEFLECTION\n",
    "to_agent_calls  = residual_calls - va_calls\n",
    "deflected_total = bot_calls + va_calls\n",
    "\n",
    "# Raw labour avoided (no haircuts)\n",
    "raw_labour_avoided = deflected_total * _aht_seconds * _labour_rate\n",
    "# After realization haircuts\n",
    "real_labour_avoided = raw_labour_avoided * real_factor\n",
    "\n",
    "# Waterfall: starting at 100% of calls, show where they go\n",
    "fig = go.Figure(go.Waterfall(\n",
    "    name=\"Call flow\",\n",
    "    orientation=\"v\",\n",
    "    measure=[\"absolute\", \"relative\", \"relative\", \"relative\", \"total\"],\n",
    "    x=[\n",
    "        f\"Total calls<br>({_annual_calls:,.0f})\",\n",
    "        f\"Voice Bot<br>(−{bot_calls:,.0f})\",\n",
    "        f\"Agentic VA<br>(−{va_calls:,.0f})\",\n",
    "        f\"To agent<br>({to_agent_calls:,.0f})\",\n",
    "        \"Net to agent\",\n",
    "    ],\n",
    "    y=[_annual_calls, -bot_calls, -va_calls, 0, 0],\n",
    "    text=[\n",
    "        f\"100%\",\n",
    "        f\"−{VA_BOT_DEFLECTION*100:.0f}%\",\n",
    "        f\"−{VA_AGENTIC_DEFLECTION*100:.0f}% of residual\",\n",
    "        \"\",\n",
    "        f\"{(to_agent_calls/_annual_calls)*100:.1f}%\",\n",
    "    ],\n",
    "    textposition=\"outside\",\n",
    "    increasing={\"marker\": {\"color\": \"#2E7D32\"}},\n",
    "    decreasing={\"marker\": {\"color\": \"#C62828\"}},\n",
    "    totals={\"marker\": {\"color\": \"#1565C0\"}},\n",
    "))\n",
    "fig.update_layout(\n",
    "    title=f\"NAM deflection cascade · {SCENARIO} scenario · \"\n",
    "          f\"{deflected_total/_annual_calls*100:.1f}% effective deflection\",\n",
    "    yaxis_title=\"Annual calls\",\n",
    "    height=420,\n",
    "    margin=dict(l=20, r=20, t=60, b=40),\n",
    ")\n",
    "fig.show()\n",
    "\n",
    "# Summary table\n",
    "summary = pd.DataFrame([\n",
    "    {\"layer\": \"Voice Bot deflection\",\n",
    "     \"% of total\": f\"{VA_BOT_DEFLECTION*100:.1f}%\",\n",
    "     \"annual calls\": bot_calls,\n",
    "     \"labour avoided (raw)\": bot_calls * _aht_seconds * _labour_rate,\n",
    "     \"labour avoided (realized)\": bot_calls * _aht_seconds * _labour_rate * real_factor},\n",
    "    {\"layer\": \"Agentic VA deflection (residual)\",\n",
    "     \"% of total\": f\"{(va_calls/_annual_calls)*100:.1f}%\",\n",
    "     \"annual calls\": va_calls,\n",
    "     \"labour avoided (raw)\": va_calls * _aht_seconds * _labour_rate,\n",
    "     \"labour avoided (realized)\": va_calls * _aht_seconds * _labour_rate * real_factor},\n",
    "    {\"layer\": \"Combined (effective)\",\n",
    "     \"% of total\": f\"{(deflected_total/_annual_calls)*100:.2f}%\",\n",
    "     \"annual calls\": deflected_total,\n",
    "     \"labour avoided (raw)\": raw_labour_avoided,\n",
    "     \"labour avoided (realized)\": real_labour_avoided},\n",
    "])\n",
    "display(summary)\n",
    "print(f\"NAM realization haircut: ${raw_labour_avoided:,.0f} raw → \"\n",
    "      f\"${real_labour_avoided:,.0f} realized \"\n",
    "      f\"(×{real_factor:.3f} = {VA_COMPLETION_RATE:.0%} completion × \"\n",
    "      f\"{VA_LABOUR_REALIZATION:.0%} labour × {1-VA_CALLBACK_DISCOUNT:.0%} retained)\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e7fc3a73",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>input</th>\n",
       "      <th>value</th>\n",
       "      <th>drives</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Voice Bot deflection (full pool)</td>\n",
       "      <td>35%</td>\n",
       "      <td>Voice Bot tokens (cost) + bot deflection benefit</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Voice Bot avg minutes</td>\n",
       "      <td>1.5 min</td>\n",
       "      <td>Voice Bot tokens (cost only)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Agentic VA deflection (residual)</td>\n",
       "      <td>15%</td>\n",
       "      <td>Agentic VA tokens (cost) + VA deflection benefit</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Effective combined deflection</td>\n",
       "      <td>44.75%</td>\n",
       "      <td>Total share of voice calls deflected</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Realization factor</td>\n",
       "      <td>53.2%</td>\n",
       "      <td>Haircut on labour avoided (70% × 80% × 95%)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                              input    value  \\\n",
       "0  Voice Bot deflection (full pool)      35%   \n",
       "1             Voice Bot avg minutes  1.5 min   \n",
       "2  Agentic VA deflection (residual)      15%   \n",
       "3     Effective combined deflection   44.75%   \n",
       "4                Realization factor    53.2%   \n",
       "\n",
       "                                             drives  \n",
       "0  Voice Bot tokens (cost) + bot deflection benefit  \n",
       "1                      Voice Bot tokens (cost only)  \n",
       "2  Agentic VA tokens (cost) + VA deflection benefit  \n",
       "3              Total share of voice calls deflected  \n",
       "4       Haircut on labour avoided (70% × 80% × 95%)  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>model</th>\n",
       "      <th>Y2 benefit</th>\n",
       "      <th>vs corrected</th>\n",
       "      <th>note</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Original (broken) — additive on full base, no ...</td>\n",
       "      <td>29,993,898</td>\n",
       "      <td></td>\n",
       "      <td>Counts bot + VA on the same call pool, 100% la...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Corrected — layered + 'claim' params (no hairc...</td>\n",
       "      <td>24,900,726</td>\n",
       "      <td>-17.0%</td>\n",
       "      <td>Layered model alone removes double-count</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Corrected — layered + realistic haircuts (curr...</td>\n",
       "      <td>13,247,186</td>\n",
       "      <td>-55.8%</td>\n",
       "      <td>Production-calibrated; this is what flows into...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model  Y2 benefit vs corrected  \\\n",
       "0  Original (broken) — additive on full base, no ...  29,993,898                \n",
       "1  Corrected — layered + 'claim' params (no hairc...  24,900,726       -17.0%   \n",
       "2  Corrected — layered + realistic haircuts (curr...  13,247,186       -55.8%   \n",
       "\n",
       "                                                note  \n",
       "0  Counts bot + VA on the same call pool, 100% la...  \n",
       "1           Layered model alone removes double-count  \n",
       "2  Production-calibrated; this is what flows into...  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Reconciliation: how the inputs above flow into both the Cost Model and\n",
    "# Benefit Model. Compare the corrected (layered + haircut) figures\n",
    "# against the original Genesys ROI-doc 'claim' assumption to make the\n",
    "# correction visible.\n",
    "\n",
    "from tokencalc.benefit_model import calculate_va_deflection_benefit\n",
    "\n",
    "# Use a year where both Voice Bot AND Agentic VA are active. In the\n",
    "# default rollout that's year 2 onward (Agentic VA phase=2).\n",
    "_RECON_YEAR = max(YEAR, 2)\n",
    "\n",
    "_bot_scope = next(s for s in scopes if s.feature == \"Voice Bot\")\n",
    "_va_scope  = next((s for s in scopes if s.feature == \"Agentic Virtual Agent\"), None)\n",
    "\n",
    "_bot_realistic = calculate_va_deflection_benefit(\n",
    "    sites, _bot_scope, scenario, _RECON_YEAR, params=\"realistic\"\n",
    ")[\"annual_value\"].sum()\n",
    "_bot_claim = calculate_va_deflection_benefit(\n",
    "    sites, _bot_scope, scenario, _RECON_YEAR, params=\"claim\"\n",
    ")[\"annual_value\"].sum()\n",
    "\n",
    "if _va_scope is not None:\n",
    "    _va_realistic = calculate_va_deflection_benefit(\n",
    "        sites, _va_scope, scenario, _RECON_YEAR, params=\"realistic\"\n",
    "    )[\"annual_value\"].sum()\n",
    "    _va_claim = calculate_va_deflection_benefit(\n",
    "        sites, _va_scope, scenario, _RECON_YEAR, params=\"claim\"\n",
    "    )[\"annual_value\"].sum()\n",
    "else:\n",
    "    _va_realistic = _va_claim = 0.0\n",
    "\n",
    "# What the (broken) additive model would have produced — naive sum on full base\n",
    "_total_calls_yr = sum(s.voice_volume_monthly * 12 for s in sites)\n",
    "_avg_labour = sum(\n",
    "    (s.voice_volume_monthly * 12) * s.voice_aht_seconds * s.agent_cost_per_second\n",
    "    for s in sites\n",
    ") / max(_total_calls_yr, 1)\n",
    "_naive_additive_claim = (\n",
    "    _total_calls_yr * (VA_BOT_DEFLECTION + VA_AGENTIC_DEFLECTION) * _avg_labour\n",
    "    * scenario.realization(_RECON_YEAR)\n",
    ")  # original error: rates added on full base, no haircuts\n",
    "\n",
    "_recon = pd.DataFrame([\n",
    "    {\"input\": \"Voice Bot deflection (full pool)\",\n",
    "     \"value\": f\"{VA_BOT_DEFLECTION:.0%}\",\n",
    "     \"drives\": \"Voice Bot tokens (cost) + bot deflection benefit\"},\n",
    "    {\"input\": \"Voice Bot avg minutes\",\n",
    "     \"value\": f\"{VA_BOT_AVG_MINUTES:.1f} min\",\n",
    "     \"drives\": \"Voice Bot tokens (cost only)\"},\n",
    "    {\"input\": \"Agentic VA deflection (residual)\",\n",
    "     \"value\": f\"{VA_AGENTIC_DEFLECTION:.0%}\",\n",
    "     \"drives\": \"Agentic VA tokens (cost) + VA deflection benefit\"},\n",
    "    {\"input\": \"Effective combined deflection\",\n",
    "     \"value\": f\"{(VA_BOT_DEFLECTION + (1-VA_BOT_DEFLECTION)*VA_AGENTIC_DEFLECTION):.2%}\",\n",
    "     \"drives\": \"Total share of voice calls deflected\"},\n",
    "    {\"input\": \"Realization factor\",\n",
    "     \"value\": f\"{real_factor:.1%}\",\n",
    "     \"drives\": \"Haircut on labour avoided \"\n",
    "               f\"({VA_COMPLETION_RATE:.0%} × {VA_LABOUR_REALIZATION:.0%} × \"\n",
    "               f\"{1-VA_CALLBACK_DISCOUNT:.0%})\"},\n",
    "])\n",
    "display(_recon)\n",
    "\n",
    "_compare = pd.DataFrame([\n",
    "    {\"model\": \"Original (broken) — additive on full base, no haircuts\",\n",
    "     f\"Y{_RECON_YEAR} benefit\": _naive_additive_claim,\n",
    "     \"vs corrected\": \"\",\n",
    "     \"note\": \"Counts bot + VA on the same call pool, 100% labour avoidance\"},\n",
    "    {\"model\": \"Corrected — layered + 'claim' params (no haircuts)\",\n",
    "     f\"Y{_RECON_YEAR} benefit\": _bot_claim + _va_claim,\n",
    "     \"vs corrected\": f\"{((_bot_claim+_va_claim)/_naive_additive_claim - 1)*100:+.1f}%\",\n",
    "     \"note\": \"Layered model alone removes double-count\"},\n",
    "    {\"model\": \"Corrected — layered + realistic haircuts (current)\",\n",
    "     f\"Y{_RECON_YEAR} benefit\": _bot_realistic + _va_realistic,\n",
    "     \"vs corrected\": f\"{((_bot_realistic+_va_realistic)/_naive_additive_claim - 1)*100:+.1f}%\",\n",
    "     \"note\": \"Production-calibrated; this is what flows into the business case\"},\n",
    "])\n",
    "display(_compare)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3079316e",
   "metadata": {},
   "source": [
    "## Cost model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "3ac4fee1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>cost_line</th>\n",
       "      <th>scope</th>\n",
       "      <th>annual_cost</th>\n",
       "      <th>confidence</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Genesys CX 3 platform licences</td>\n",
       "      <td>all sites</td>\n",
       "      <td>2,788,232</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Agent Copilot [named]</td>\n",
       "      <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
       "      <td>1,002,240</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Speech &amp; Text Analytics [named]</td>\n",
       "      <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
       "      <td>751,680</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Voice Bot</td>\n",
       "      <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
       "      <td>680,592</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Direct Messaging</td>\n",
       "      <td>NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...</td>\n",
       "      <td>132</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Agentic Virtual Agent</td>\n",
       "      <td>—</td>\n",
       "      <td>0</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>AI Summary &amp; Insights</td>\n",
       "      <td>—</td>\n",
       "      <td>0</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Email AI (Auto-Suggest)</td>\n",
       "      <td>—</td>\n",
       "      <td>0</td>\n",
       "      <td>unknown</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>AI Translate</td>\n",
       "      <td>—</td>\n",
       "      <td>0</td>\n",
       "      <td>confirmed</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                         cost_line  \\\n",
       "0   Genesys CX 3 platform licences   \n",
       "4            Agent Copilot [named]   \n",
       "3  Speech & Text Analytics [named]   \n",
       "1                        Voice Bot   \n",
       "6                 Direct Messaging   \n",
       "2            Agentic Virtual Agent   \n",
       "5            AI Summary & Insights   \n",
       "7          Email AI (Auto-Suggest)   \n",
       "8                     AI Translate   \n",
       "\n",
       "                                               scope  annual_cost confidence  \n",
       "0                                          all sites    2,788,232  confirmed  \n",
       "4  NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...    1,002,240  confirmed  \n",
       "3  NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...      751,680  confirmed  \n",
       "1  NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...      680,592  confirmed  \n",
       "6  NAM, EMEA, AUZ, APAC HK, APAC SG, APAC SH, APA...          132  confirmed  \n",
       "2                                                  —            0  confirmed  \n",
       "5                                                  —            0  confirmed  \n",
       "7                                                  —            0    unknown  \n",
       "8                                                  —            0  confirmed  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Year 1 total: $5,222,876   (of which 🔴 unknown-rate features: $0)\n"
     ]
    }
   ],
   "source": [
    "cost_df = calculate_total_cost(sites, scopes, meters, pricing, scenario, YEAR,\n",
    "                               use_contracted=USE_CONTRACTED_RATES)\n",
    "display(cost_df.sort_values(\"annual_cost\", ascending=False))\n",
    "unknown_cost = cost_df[cost_df.confidence == \"unknown\"][\"annual_cost\"].sum()\n",
    "print(f\"Year {YEAR} total: ${cost_df['annual_cost'].sum():,.0f}\"\n",
    "      f\"   (of which 🔴 unknown-rate features: ${unknown_cost:,.0f})\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fa4c9cdc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "hovertemplate": "cost_line=Genesys CX 3 platform licences<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Genesys CX 3 platform licences",
         "marker": {
          "color": "#636efa",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Genesys CX 3 platform licences",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "cT0K18NFRUFxPQrXw0VFQXE9CtfDRUVB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=Voice Bot<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Voice Bot",
         "marker": {
          "color": "#EF553B",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Voice Bot",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAACDFJEEAAAAAoKstQQAAAACgqy1B",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=Agentic Virtual Agent<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Agentic Virtual Agent",
         "marker": {
          "color": "#00cc96",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Agentic Virtual Agent",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAAAAAAAAAAAAaII4QQAAAAC4gUFB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=Speech & Text Analytics [named]<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Speech & Text Analytics [named]",
         "marker": {
          "color": "#ab63fa",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Speech & Text Analytics [named]",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAIDwJkEAAAAAgPAmQQAAAACA8CZB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=Agent Copilot [named]<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Agent Copilot [named]",
         "marker": {
          "color": "#FFA15A",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Agent Copilot [named]",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAACWLkEAAAAAAJYuQQAAAAAAli5B",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=AI Summary & Insights<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "AI Summary & Insights",
         "marker": {
          "color": "#19d3f3",
          "pattern": {
           "shape": ""
          }
         },
         "name": "AI Summary & Insights",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=Direct Messaging<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Direct Messaging",
         "marker": {
          "color": "#FF6692",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Direct Messaging",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAACAYEAAAAAAAABiQAAAAAAAAGJA",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=Email AI (Auto-Suggest)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Email AI (Auto-Suggest)",
         "marker": {
          "color": "#B6E880",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Email AI (Auto-Suggest)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "cost_line=AI Translate<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "AI Translate",
         "marker": {
          "color": "#FF97FF",
          "pattern": {
           "shape": ""
          }
         },
         "name": "AI Translate",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAU6lBB",
          "dtype": "f8"
         },
         "yaxis": "y"
        }
       ],
       "layout": {
        "barmode": "relative",
        "legend": {
         "title": {
          "text": "cost_line"
         },
         "tracegroupgap": 0
        },
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "Cost breakdown by feature — realistic"
        },
        "xaxis": {
         "anchor": "y",
         "domain": [
          0,
          1
         ],
         "title": {
          "text": "year"
         }
        },
        "yaxis": {
         "anchor": "x",
         "domain": [
          0,
          1
         ],
         "title": {
          "text": "$/yr"
         }
        }
       }
      },
      "image/png": "[encoded data, 61764 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Stacked bar — cost by feature, one bar per year\n",
    "frames = []\n",
    "for y in (1, 2, 3):\n",
    "    d = calculate_total_cost(sites, scopes, meters, pricing, scenario, y,\n",
    "                             use_contracted=USE_CONTRACTED_RATES)\n",
    "    d[\"year\"] = f\"Y{y}\"\n",
    "    frames.append(d)\n",
    "cost_3y = pd.concat(frames, ignore_index=True)\n",
    "px.bar(cost_3y, x=\"year\", y=\"annual_cost\", color=\"cost_line\",\n",
    "       title=f\"Cost breakdown by feature — {SCENARIO}\",\n",
    "       labels={\"annual_cost\": \"$/yr\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "326602c1",
   "metadata": {},
   "source": [
    "## Benefit model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "380914e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>benefit_line</th>\n",
       "      <th>scope</th>\n",
       "      <th>annual_value</th>\n",
       "      <th>confidence</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Voice Bot deflection (labour avoided)</td>\n",
       "      <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
       "      <td>6,981,080</td>\n",
       "      <td>estimated</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Voice ACW (summarization)</td>\n",
       "      <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
       "      <td>2,099,573</td>\n",
       "      <td>estimated</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Voice AHT (knowledge surfacing)</td>\n",
       "      <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
       "      <td>1,237,248</td>\n",
       "      <td>estimated</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>STA coaching (AHT)</td>\n",
       "      <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
       "      <td>562,386</td>\n",
       "      <td>estimated</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Supervisor time (AI summaries/insights)</td>\n",
       "      <td>APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...</td>\n",
       "      <td>318,500</td>\n",
       "      <td>estimated</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                              benefit_line  \\\n",
       "0    Voice Bot deflection (labour avoided)   \n",
       "3                Voice ACW (summarization)   \n",
       "2          Voice AHT (knowledge surfacing)   \n",
       "1                       STA coaching (AHT)   \n",
       "4  Supervisor time (AI summaries/insights)   \n",
       "\n",
       "                                               scope  annual_value confidence  \n",
       "0  APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...     6,981,080  estimated  \n",
       "3  APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...     2,099,573  estimated  \n",
       "2  APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...     1,237,248  estimated  \n",
       "1  APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...       562,386  estimated  \n",
       "4  APAC GZ, APAC HK, APAC JP, APAC SG, APAC SH, A...       318,500  estimated  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Year 1 total benefit: $11,198,787\n"
     ]
    }
   ],
   "source": [
    "benefit_df = calculate_total_benefit(sites, scopes, scenario, YEAR,\n",
    "                                     params=BENEFIT_PARAMS_MODE)\n",
    "display(benefit_df.sort_values(\"annual_value\", ascending=False))\n",
    "print(f\"Year {YEAR} total benefit: ${benefit_df['annual_value'].sum():,.0f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ae5fb48b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "hovertemplate": "benefit_line=Voice Bot deflection (labour avoided)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Voice Bot deflection (labour avoided)",
         "marker": {
          "color": "#636efa",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Voice Bot deflection (labour avoided)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "DvzA8XWhWkE/Y5r0901lQdtVd3KWTGlB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "benefit_line=STA coaching (AHT)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "STA coaching (AHT)",
         "marker": {
          "color": "#EF553B",
          "pattern": {
           "shape": ""
          }
         },
         "name": "STA coaching (AHT)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "ndiJLaMpIUFjJ3bi0XUrQWIndp70TTBB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "benefit_line=Voice AHT (knowledge surfacing)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Voice AHT (knowledge surfacing)",
         "marker": {
          "color": "#00cc96",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Voice AHT (knowledge surfacing)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "FDuxSwDhMkGGXuhFzTQ+QR/4geFZ70FB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "benefit_line=Voice ACW (summarization)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Voice ACW (summarization)",
         "marker": {
          "color": "#ab63fa",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Voice ACW (summarization)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "T+zEbroEQEFLrdRKKqFJQcmN3Dhib05B",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "benefit_line=Supervisor time (AI summaries/insights)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Supervisor time (AI summaries/insights)",
         "marker": {
          "color": "#FFA15A",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Supervisor time (AI summaries/insights)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y1",
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "AAAAAJBwE0EAAAAAgBofQQAAAAC8dyJB",
          "dtype": "f8"
         },
         "yaxis": "y"
        },
        {
         "hovertemplate": "benefit_line=Agentic Virtual Agent deflection (labour avoided)<br>year=%{x}<br>$/yr=%{y}<extra></extra>",
         "legendgroup": "Agentic Virtual Agent deflection (labour avoided)",
         "marker": {
          "color": "#19d3f3",
          "pattern": {
           "shape": ""
          }
         },
         "name": "Agentic Virtual Agent deflection (labour avoided)",
         "orientation": "v",
         "showlegend": true,
         "textposition": "auto",
         "type": "bar",
         "x": [
          "Y2",
          "Y3"
         ],
         "xaxis": "x",
         "y": {
          "bdata": "lkOLvBKzP0EgsPIfU9JCQQ==",
          "dtype": "f8"
         },
         "yaxis": "y"
        }
       ],
       "layout": {
        "barmode": "relative",
        "legend": {
         "title": {
          "text": "benefit_line"
         },
         "tracegroupgap": 0
        },
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "Benefit breakdown by source — realistic"
        },
        "xaxis": {
         "anchor": "y",
         "domain": [
          0,
          1
         ],
         "title": {
          "text": "year"
         }
        },
        "yaxis": {
         "anchor": "x",
         "domain": [
          0,
          1
         ],
         "title": {
          "text": "$/yr"
         }
        }
       }
      },
      "image/png": "[encoded data, 61624 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "name": "Genesys claim",
         "type": "bar",
         "x": [
          "STA coaching (AHT)",
          "Supervisor time (AI summaries/insights)",
          "Voice ACW (summarization)",
          "Voice AHT (knowledge surfacing)",
          "Voice Bot deflection (labour avoided)"
         ],
         "y": {
          "bdata": "J3Zi5y7iNkEAAAAAkHAjQWIndgrpBVRB8AM/6AQiQEE7sRNNYwdpQQ==",
          "dtype": "f8"
         }
        },
        {
         "name": "Pressure-tested realistic",
         "type": "bar",
         "x": [
          "STA coaching (AHT)",
          "Supervisor time (AI summaries/insights)",
          "Voice ACW (summarization)",
          "Voice AHT (knowledge surfacing)",
          "Voice Bot deflection (labour avoided)"
         ],
         "y": {
          "bdata": "ndiJLaMpIUEAAAAAkHATQU/sxG66BEBBFDuxSwDhMkEO/MDxdaFaQQ==",
          "dtype": "f8"
         }
        }
       ],
       "layout": {
        "barmode": "group",
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "Claim vs pressure-tested — Year 1"
        },
        "yaxis": {
         "tickformat": "$,.0f"
        }
       }
      },
      "image/png": "[encoded data, 65528 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Stacked bar by source per year + Genesys claim vs pressure-tested comparison\n",
    "frames = []\n",
    "for y in (1, 2, 3):\n",
    "    d = calculate_total_benefit(sites, scopes, scenario, y, params=BENEFIT_PARAMS_MODE)\n",
    "    d[\"year\"] = f\"Y{y}\"\n",
    "    frames.append(d)\n",
    "ben_3y = pd.concat(frames, ignore_index=True)\n",
    "fig = px.bar(ben_3y, x=\"year\", y=\"annual_value\", color=\"benefit_line\",\n",
    "             title=f\"Benefit breakdown by source — {SCENARIO}\",\n",
    "             labels={\"annual_value\": \"$/yr\"})\n",
    "fig.show()\n",
    "\n",
    "claim = calculate_total_benefit(sites, scopes, scenario, YEAR, params=\"claim\")\n",
    "comp = pd.merge(\n",
    "    claim[[\"benefit_line\", \"annual_value\"]].rename(columns={\"annual_value\": \"Genesys claim\"}),\n",
    "    benefit_df[[\"benefit_line\", \"annual_value\"]].rename(columns={\"annual_value\": \"Pressure-tested\"}),\n",
    "    on=\"benefit_line\", how=\"outer\",\n",
    ").fillna(0)\n",
    "go.Figure([\n",
    "    go.Bar(name=\"Genesys claim\", x=comp.benefit_line, y=comp[\"Genesys claim\"]),\n",
    "    go.Bar(name=\"Pressure-tested realistic\", x=comp.benefit_line, y=comp[\"Pressure-tested\"]),\n",
    "]).update_layout(barmode=\"group\", title=f\"Claim vs pressure-tested — Year {YEAR}\",\n",
    "                 yaxis_tickformat=\"$,.0f\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33e2dc31",
   "metadata": {},
   "source": [
    "## Business case — 3-year P&L, NPV @ 8%, payback, ROI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "7bd6456e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>line</th>\n",
       "      <th>Y1</th>\n",
       "      <th>Y2</th>\n",
       "      <th>Y3</th>\n",
       "      <th>3-yr Total</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Genesys CX 3 platform licences</td>\n",
       "      <td>2,788,232</td>\n",
       "      <td>2,788,232</td>\n",
       "      <td>2,788,232</td>\n",
       "      <td>8,364,695</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Voice Bot</td>\n",
       "      <td>680,592</td>\n",
       "      <td>972,240</td>\n",
       "      <td>972,240</td>\n",
       "      <td>2,625,072</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Agentic Virtual Agent</td>\n",
       "      <td>0</td>\n",
       "      <td>1,606,248</td>\n",
       "      <td>2,294,640</td>\n",
       "      <td>3,900,888</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Speech &amp; Text Analytics [named]</td>\n",
       "      <td>751,680</td>\n",
       "      <td>751,680</td>\n",
       "      <td>751,680</td>\n",
       "      <td>2,255,040</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Agent Copilot [named]</td>\n",
       "      <td>1,002,240</td>\n",
       "      <td>1,002,240</td>\n",
       "      <td>1,002,240</td>\n",
       "      <td>3,006,720</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>AI Summary &amp; Insights</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Direct Messaging</td>\n",
       "      <td>132</td>\n",
       "      <td>144</td>\n",
       "      <td>144</td>\n",
       "      <td>420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Email AI (Auto-Suggest)</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>AI Translate</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>4,434,000</td>\n",
       "      <td>4,434,000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>NICE IEX (NAM)</td>\n",
       "      <td>650,000</td>\n",
       "      <td>1,300,000</td>\n",
       "      <td>1,300,000</td>\n",
       "      <td>3,250,000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>Legacy CC platform</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>Voice Bot deflection (labour avoided)</td>\n",
       "      <td>6,981,080</td>\n",
       "      <td>11,169,728</td>\n",
       "      <td>13,264,052</td>\n",
       "      <td>31,414,859</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>STA coaching (AHT)</td>\n",
       "      <td>562,386</td>\n",
       "      <td>899,817</td>\n",
       "      <td>1,068,533</td>\n",
       "      <td>2,530,735</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>Voice AHT (knowledge surfacing)</td>\n",
       "      <td>1,237,248</td>\n",
       "      <td>1,979,597</td>\n",
       "      <td>2,350,772</td>\n",
       "      <td>5,567,617</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>Voice ACW (summarization)</td>\n",
       "      <td>2,099,573</td>\n",
       "      <td>3,359,317</td>\n",
       "      <td>3,989,188</td>\n",
       "      <td>9,448,078</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>Supervisor time (AI summaries/insights)</td>\n",
       "      <td>318,500</td>\n",
       "      <td>509,600</td>\n",
       "      <td>605,150</td>\n",
       "      <td>1,433,250</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>Agentic Virtual Agent deflection (labour avoided)</td>\n",
       "      <td>0</td>\n",
       "      <td>2,077,459</td>\n",
       "      <td>2,466,982</td>\n",
       "      <td>4,544,441</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>TOTAL COSTS</td>\n",
       "      <td>5,222,876</td>\n",
       "      <td>7,120,784</td>\n",
       "      <td>12,243,176</td>\n",
       "      <td>24,586,835</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>TOTAL TAKEOUTS</td>\n",
       "      <td>650,000</td>\n",
       "      <td>1,300,000</td>\n",
       "      <td>1,300,000</td>\n",
       "      <td>3,250,000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>TOTAL BENEFITS</td>\n",
       "      <td>11,198,787</td>\n",
       "      <td>19,995,517</td>\n",
       "      <td>23,744,677</td>\n",
       "      <td>54,938,980</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>NET</td>\n",
       "      <td>6,625,911</td>\n",
       "      <td>14,174,734</td>\n",
       "      <td>12,801,501</td>\n",
       "      <td>33,602,145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>Cumulative net</td>\n",
       "      <td>6,625,911</td>\n",
       "      <td>20,800,644</td>\n",
       "      <td>33,602,145</td>\n",
       "      <td>61,028,701</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                 line         Y1         Y2  \\\n",
       "0                      Genesys CX 3 platform licences  2,788,232  2,788,232   \n",
       "1                                           Voice Bot    680,592    972,240   \n",
       "2                               Agentic Virtual Agent          0  1,606,248   \n",
       "3                     Speech & Text Analytics [named]    751,680    751,680   \n",
       "4                               Agent Copilot [named]  1,002,240  1,002,240   \n",
       "5                               AI Summary & Insights          0          0   \n",
       "6                                    Direct Messaging        132        144   \n",
       "7                             Email AI (Auto-Suggest)          0          0   \n",
       "8                                        AI Translate          0          0   \n",
       "9                                      NICE IEX (NAM)    650,000  1,300,000   \n",
       "10                                 Legacy CC platform          0          0   \n",
       "11              Voice Bot deflection (labour avoided)  6,981,080 11,169,728   \n",
       "12                                 STA coaching (AHT)    562,386    899,817   \n",
       "13                    Voice AHT (knowledge surfacing)  1,237,248  1,979,597   \n",
       "14                          Voice ACW (summarization)  2,099,573  3,359,317   \n",
       "15            Supervisor time (AI summaries/insights)    318,500    509,600   \n",
       "16  Agentic Virtual Agent deflection (labour avoided)          0  2,077,459   \n",
       "17                                        TOTAL COSTS  5,222,876  7,120,784   \n",
       "18                                     TOTAL TAKEOUTS    650,000  1,300,000   \n",
       "19                                     TOTAL BENEFITS 11,198,787 19,995,517   \n",
       "20                                                NET  6,625,911 14,174,734   \n",
       "21                                     Cumulative net  6,625,911 20,800,644   \n",
       "\n",
       "           Y3  3-yr Total  \n",
       "0   2,788,232   8,364,695  \n",
       "1     972,240   2,625,072  \n",
       "2   2,294,640   3,900,888  \n",
       "3     751,680   2,255,040  \n",
       "4   1,002,240   3,006,720  \n",
       "5           0           0  \n",
       "6         144         420  \n",
       "7           0           0  \n",
       "8   4,434,000   4,434,000  \n",
       "9   1,300,000   3,250,000  \n",
       "10          0           0  \n",
       "11 13,264,052  31,414,859  \n",
       "12  1,068,533   2,530,735  \n",
       "13  2,350,772   5,567,617  \n",
       "14  3,989,188   9,448,078  \n",
       "15    605,150   1,433,250  \n",
       "16  2,466,982   4,544,441  \n",
       "17 12,243,176  24,586,835  \n",
       "18  1,300,000   3,250,000  \n",
       "19 23,744,677  54,938,980  \n",
       "20 12,801,501  33,602,145  \n",
       "21 33,602,145  61,028,701  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NPV @ 8%: $28,449,896   Payback: 0.00 years   3-yr ROI: 137%\n"
     ]
    }
   ],
   "source": [
    "case = build_business_case(sites, scopes, meters, pricing, takeouts, scenario,\n",
    "                           implementation_cost=IMPLEMENTATION_COST,\n",
    "                           use_contracted=USE_CONTRACTED_RATES,\n",
    "                           benefit_params=BENEFIT_PARAMS_MODE)\n",
    "\n",
    "pnl = pd.concat([\n",
    "    case[\"cost_by_year\"].drop(columns=\"confidence\"),\n",
    "    case[\"takeouts_by_year\"].drop(columns=\"confidence\"),\n",
    "    case[\"benefit_by_year\"].drop(columns=\"confidence\"),\n",
    "    case[\"net_by_year\"],\n",
    "], ignore_index=True)\n",
    "pnl[\"3-yr Total\"] = pnl[[\"Y1\", \"Y2\", \"Y3\"]].sum(axis=1)\n",
    "display(pnl)\n",
    "\n",
    "pb = case[\"payback_period_years\"]\n",
    "pb_text = f\"{pb:.2f} years\" if pb is not None else \"never\"\n",
    "print(f\"NPV @ 8%: ${case['npv']:,.0f}   Payback: {pb_text}   \"\n",
    "      f\"3-yr ROI: {case['roi_3yr']:.0%}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "c869422e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "mode": "lines+markers",
         "name": "Floor",
         "type": "scatter",
         "x": {
          "bdata": "AQID",
          "dtype": "i1"
         },
         "y": {
          "bdata": "kAHmzPfxOkFcMJWpTCZjQS9Qu52k7HBB",
          "dtype": "f8"
         }
        },
        {
         "mode": "lines+markers",
         "name": "Realistic",
         "type": "scatter",
         "x": {
          "bdata": "AQID",
          "dtype": "i1"
         },
         "y": {
          "bdata": "WN07tp1GWUFNYpBFSNZzQWInjgrTBYBB",
          "dtype": "f8"
         }
        },
        {
         "mode": "lines+markers",
         "name": "Stretch",
         "type": "scatter",
         "x": {
          "bdata": "AQID",
          "dtype": "i1"
         },
         "y": {
          "bdata": "1qNwJg/IaUHmEqiU71F/QR6FGxpGI4dB",
          "dtype": "f8"
         }
        }
       ],
       "layout": {
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "Cumulative net cash flow by scenario"
        },
        "xaxis": {
         "title": {
          "text": "Year"
         }
        },
        "yaxis": {
         "tickformat": "$,.0f"
        }
       }
      },
      "image/png": "[encoded data, 59924 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Cumulative net cash flow — all three scenarios\n",
    "fig = go.Figure()\n",
    "for name in (\"floor\", \"realistic\", \"stretch\"):\n",
    "    c = build_business_case(sites, scopes, meters, pricing, takeouts, name,\n",
    "                            implementation_cost=IMPLEMENTATION_COST,\n",
    "                            benefit_params=BENEFIT_PARAMS_MODE)\n",
    "    fig.add_scatter(x=c[\"cumulative_net\"].year, y=c[\"cumulative_net\"].cumulative_net,\n",
    "                    mode=\"lines+markers\", name=name.capitalize())\n",
    "fig.update_layout(title=\"Cumulative net cash flow by scenario\",\n",
    "                  xaxis_title=\"Year\", yaxis_tickformat=\"$,.0f\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "855966ce",
   "metadata": {},
   "source": [
    "## Sensitivity — tornado & break-even"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "bab4c657",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "name": "-25%",
         "orientation": "h",
         "type": "bar",
         "x": {
          "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJskqLbE8UDAN2jxJQ4hQXDS8BGK9jHBwC6o95R7PsE=",
          "dtype": "f8"
         },
         "y": [
          "agentic_va_deflection",
          "email_auto_respond_rate",
          "email_auto_suggest_acceptance",
          "voice_bot_deflection",
          "voice_bot_avg_minutes",
          "voice_knowledge_eligibility",
          "voice_summarization_eligibility"
         ]
        },
        {
         "name": "+25%",
         "orientation": "h",
         "type": "bar",
         "x": {
          "bdata": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALJrSpjG8cCgJLkX6A0hwUDS8BGK9jFBoC6o95R7PkE=",
          "dtype": "f8"
         },
         "y": [
          "agentic_va_deflection",
          "email_auto_respond_rate",
          "email_auto_suggest_acceptance",
          "voice_bot_deflection",
          "voice_bot_avg_minutes",
          "voice_knowledge_eligibility",
          "voice_summarization_eligibility"
         ]
        }
       ],
       "layout": {
        "barmode": "overlay",
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "Tornado — NPV swing vs input ±25%"
        },
        "xaxis": {
         "tickformat": "$,.0f",
         "title": {
          "text": "Δ 3-yr NPV ($)"
         }
        }
       }
      },
      "image/png": "[encoded data, 60540 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Tornado: vary each scenario driver ±25% (clamped to 0–1), hold others\n",
    "DRIVERS = [\"voice_bot_deflection\", \"voice_bot_avg_minutes\", \"agentic_va_deflection\",\n",
    "           \"voice_summarization_eligibility\", \"voice_knowledge_eligibility\",\n",
    "           \"email_auto_respond_rate\", \"email_auto_suggest_acceptance\"]\n",
    "\n",
    "def npv_with(field, factor):\n",
    "    v = getattr(scenario, field) * factor\n",
    "    if field != \"voice_bot_avg_minutes\":\n",
    "        v = min(max(v, 0.0), 1.0)\n",
    "    sc = dataclasses.replace(scenario, **{field: v})\n",
    "    return build_business_case(sites, scopes, meters, pricing, takeouts, sc,\n",
    "                               benefit_params=BENEFIT_PARAMS_MODE)[\"npv\"]\n",
    "\n",
    "base_npv = case[\"npv\"]\n",
    "rows = [{\"driver\": d, \"low\": npv_with(d, 0.75) - base_npv,\n",
    "         \"high\": npv_with(d, 1.25) - base_npv} for d in DRIVERS]\n",
    "torn = pd.DataFrame(rows)\n",
    "torn[\"swing\"] = (torn.high - torn.low).abs()\n",
    "torn = torn.sort_values(\"swing\")\n",
    "go.Figure([\n",
    "    go.Bar(y=torn.driver, x=torn.low, orientation=\"h\", name=\"-25%\"),\n",
    "    go.Bar(y=torn.driver, x=torn.high, orientation=\"h\", name=\"+25%\"),\n",
    "]).update_layout(barmode=\"overlay\", title=\"Tornado — NPV swing vs input ±25%\",\n",
    "                 xaxis_title=\"Δ 3-yr NPV ($)\", xaxis_tickformat=\"$,.0f\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "2b3dee90",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Break-even auto-respond rate: 0% (NPV already $28,449,896 at 0%)\n"
     ]
    },
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "hovertemplate": "Email Auto-Respond rate=%{x}<br>3-yr NPV ($)=%{y}<extra></extra>",
         "legendgroup": "",
         "line": {
          "color": "#636efa",
          "dash": "solid"
         },
         "marker": {
          "symbol": "circle"
         },
         "mode": "lines",
         "name": "",
         "orientation": "v",
         "showlegend": false,
         "type": "scatter",
         "x": {
          "bdata": "AAAAAAAAAAB7FK5H4XqUP3sUrkfheqQ/uB6F61G4rj97FK5H4Xq0P5qZmZmZmbk/uB6F61G4vj/sUbgehevBP3sUrkfhesQ/CtejcD0Kxz+amZmZmZnJPylcj8L1KMw/uB6F61G4zj+kcD0K16PQP+xRuB6F69E/MzMzMzMz0z97FK5H4XrUP8P1KFyPwtU/CtejcD0K1z9SuB6F61HYP5qZmZmZmdk/4XoUrkfh2j8pXI/C9SjcP3E9CtejcN0/uB6F61G43j8AAAAAAADgPw==",
          "dtype": "f8"
         },
         "xaxis": "x",
         "y": {
          "bdata": "SGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QUhgN4LGIXtBSGA3gsYhe0FIYDeCxiF7QQ==",
          "dtype": "f8"
         },
         "yaxis": "y"
        }
       ],
       "layout": {
        "legend": {
         "tracegroupgap": 0
        },
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "#E5ECF6",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "white",
             "linecolor": "white",
             "minorgridcolor": "white",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "#E5ECF6",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "white"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "#E5ECF6",
          "polar": {
           "angularaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "radialaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "yaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           },
           "zaxis": {
            "backgroundcolor": "#E5ECF6",
            "gridcolor": "white",
            "gridwidth": 2,
            "linecolor": "white",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "white"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           },
           "bgcolor": "#E5ECF6",
           "caxis": {
            "gridcolor": "white",
            "linecolor": "white",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "white",
           "linecolor": "white",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "white",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "NPV vs email Auto-Respond rate"
        },
        "xaxis": {
         "anchor": "y",
         "domain": [
          0,
          1
         ],
         "title": {
          "text": "Email Auto-Respond rate"
         }
        },
        "yaxis": {
         "anchor": "x",
         "domain": [
          0,
          1
         ],
         "title": {
          "text": "3-yr NPV ($)"
         }
        }
       }
      },
      "image/png": "[encoded data, 41060 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Break-even: at what email Auto-Respond rate does the case break even?\n",
    "import numpy as np\n",
    "\n",
    "rates = np.linspace(0.0, 0.5, 26)\n",
    "npvs = [build_business_case(\n",
    "            sites, scopes, meters, pricing, takeouts,\n",
    "            dataclasses.replace(scenario, email_auto_respond_rate=float(r)),\n",
    "            benefit_params=BENEFIT_PARAMS_MODE)[\"npv\"]\n",
    "        for r in rates]\n",
    "breakeven = next((r for r, v in zip(rates, npvs) if v >= 0), None)\n",
    "print(\"Break-even auto-respond rate:\",\n",
    "      f\"{breakeven:.0%}\" if breakeven is not None else \"not reached ≤50%\",\n",
    "      f\"(NPV already ${npvs[0]:,.0f} at 0%)\" if npvs[0] >= 0 else \"\")\n",
    "px.line(x=rates, y=npvs, labels={\"x\": \"Email Auto-Respond rate\", \"y\": \"3-yr NPV ($)\"},\n",
    "        title=\"NPV vs email Auto-Respond rate\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c4d5a54",
   "metadata": {},
   "source": [
    "## Export"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "57611721",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Excel → /Users/robert/git/palladium/studies/202512_GenesysCX/ctm-token-calculator/exports/ctm_token_calculator_realistic.xlsx\n",
      "JSON  → /Users/robert/git/palladium/studies/202512_GenesysCX/ctm-token-calculator/exports/ctm_scenario_realistic.json\n"
     ]
    }
   ],
   "source": [
    "scenario_comparison = pd.DataFrame([\n",
    "    {\"scenario\": n,\n",
    "     **{f\"NPV\": c[\"npv\"], \"payback_years\": c[\"payback_period_years\"],\n",
    "        \"roi_3yr\": c[\"roi_3yr\"]}}\n",
    "    for n, c in ((n, build_business_case(sites, scopes, meters, pricing,\n",
    "                                         takeouts, n,\n",
    "                                         benefit_params=BENEFIT_PARAMS_MODE))\n",
    "                 for n in (\"floor\", \"realistic\", \"stretch\"))\n",
    "])\n",
    "\n",
    "xlsx = export_excel({\n",
    "    \"Inputs\": sites_dataframe(sites),\n",
    "    \"Meters\": meters_dataframe(meters),\n",
    "    \"Cost detail\": cost_3y,\n",
    "    \"Benefit detail\": ben_3y,\n",
    "    \"Business case\": pnl,\n",
    "    \"Scenario comparison\": scenario_comparison,\n",
    "}, _ROOT / \"exports\" / f\"ctm_token_calculator_{SCENARIO}.xlsx\")\n",
    "json_path = _ROOT / \"exports\" / f\"ctm_scenario_{SCENARIO}.json\"\n",
    "scenario_state_to_json(sites, takeouts, scopes, json_path)\n",
    "print(f\"Excel → {xlsx}\\nJSON  → {json_path}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec9f50a0",
   "metadata": {},
   "source": [
    "## Scratchpad\n",
    "\n",
    "Ad-hoc analysis below — e.g. per-site cost detail:\n",
    "```python\n",
    "calculate_consumption_ai_cost(sites, scopes[0], meters[\"Voice Bot\"], scenario, pricing, year=YEAR)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76d303ce",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
