Files
palladium/studies/202607_CX_AI_Diagnostic/notebooks/diagnostic.ipynb
2026-07-23 12:04:37 -04:00

10521 lines
642 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "a3634d16",
"metadata": {},
"source": [
"# CX AI Advisory Diagnostic\n",
"\n",
"The facilitator's cockpit for the CX AI Advisory diagnostic workshop:\n",
"capture capability scores across **12 competencies** in four dimensions,\n",
"ingest the client's operational baseline, and watch the **value-at-stake\n",
"analysis** — bounded by the capability gaps — recompute live in the room.\n",
"\n",
"**This notebook is the deliverable.** Serve it with\n",
"`mercury --working-dir .` from the study root and share the screen. Work\n",
"the sidebar top-to-bottom: engagement, baseline, then one competency at a\n",
"time. The stage shows the current competency's card, the heatmap, the\n",
"value analysis, and the unlock sequence. Click **Export JSON + CSV** at\n",
"the bottom to write the structured engagement record to `exports/`.\n",
"\n",
"All content and math live in `diaglib/` and `configs/*.yaml` — the\n",
"notebook only arranges and renders them. Outputs are **ranges, never\n",
"point estimates**, and money displays at two significant figures.\n",
"\n",
"Confidence legend: 🟢 known · 🟡 estimated · 🔴 unknown — flag each\n",
"baseline input; unknowns surface as explicit warnings in the analysis."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8196c6ba",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:37.330585Z",
"iopub.status.busy": "2026-07-19T23:45:37.330333Z",
"iopub.status.idle": "2026-07-19T23:45:37.878564Z",
"shell.execute_reply": "2026-07-19T23:45:37.877675Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"diaglib loaded — 12 competencies · industries: contact_center, financial_services\n"
]
}
],
"source": [
"# ── Setup ──────────────────────────────────────────────────────────\n",
"import sys, pathlib\n",
"_ROOT = pathlib.Path.cwd()\n",
"if not (_ROOT / \"diaglib\").exists(): # notebook lives in notebooks/\n",
" _ROOT = _ROOT.parent\n",
"sys.path.insert(0, str(_ROOT))\n",
"\n",
"import datetime as dt\n",
"import html as _html\n",
"\n",
"import mercury as mr\n",
"import pandas as pd\n",
"from IPython.display import display\n",
"\n",
"# Single source of truth — all math and content live in the library;\n",
"# only presentation (and Mercury widgets) lives here.\n",
"from diaglib import (\n",
" BASELINE_FIELDS, CONFIDENCE_ICON, CSV_COLUMNS,\n",
" OperationalBaseline, backstage, build_engagement, build_scores,\n",
" configs_dir, dimension_rollup, engagement_json, evidence_coverage,\n",
" heatmap_fig, heatmap_grid, list_industries, load_config, money,\n",
" parse_participants, scores_dataframe, split_fig, unlock_fig,\n",
" value_at_stake, value_bands_fig, write_exports,\n",
")\n",
"\n",
"pd.options.display.float_format = \"{:,.0f}\".format\n",
"\n",
"CONFIGS_DIR = configs_dir(_ROOT)\n",
"EXPORTS_DIR = _ROOT / \"exports\"\n",
"INDUSTRIES = list_industries(CONFIGS_DIR)\n",
"# The competency model is industry-independent (overlays may not redefine\n",
"# it — the loader enforces that), so widgets can build from any config.\n",
"_BASE = load_config(\"contact_center\", CONFIGS_DIR)\n",
"COMPETENCIES = _BASE.competencies\n",
"DIMENSION_NAME = {d.id: d.name for d in _BASE.dimensions}\n",
"\n",
"# ── Brand palette (docs/brand.md, light theme) ─────────────────────\n",
"NAVY, INK, MUTED = \"#151d2c\", \"#2e404d\", \"#586671\"\n",
"BLUE, GREEN, LINE = \"#0072bc\", \"#00a34c\", \"#e2e6e9\"\n",
"CARD_BG, HAIRLINE, HILITE = \"#f8f8f8\", \"#d5d9db\", \"#dcecfa\"\n",
"FONT = \"Georgia, 'Times New Roman', serif\"\n",
"BODY_FONT = \"Arial, 'Helvetica Neue', Helvetica, sans-serif\"\n",
"\n",
"\n",
"def esc(s):\n",
" return _html.escape(str(s))\n",
"\n",
"\n",
"# ── Workshop seeds — the gate's mock scenario; overwrite live ──────\n",
"# Headless nbconvert renders every widget at its seed, so the seeds form\n",
"# a coherent, gate-passing scenario (Pattern §3).\n",
"SEED_CLIENT = \"Acme Demo Co\"\n",
"SEED_DATE = \"2026-07-19\"\n",
"SEED_FACILITATOR = \"Robert Helewka\"\n",
"SEED_PARTICIPANTS = (\"Jane Example | VP Customer Experience | cx; \"\n",
" \"Sam Sample | Contact Center Ops Director | ops\")\n",
"SEED_BASELINE = {\n",
" \"annual_contact_volume\": 1_200_000,\n",
" \"blended_cost_per_contact\": 6.50,\n",
" \"agent_headcount\": 450,\n",
" \"annual_attrition_rate\": 0.30,\n",
" \"current_containment_rate\": 0.20,\n",
" \"average_handle_time_seconds\": 420,\n",
"}\n",
"CONFIDENCE_CHOICES = [\"🟢 known\", \"🟡 estimated\", \"🔴 unknown\"]\n",
"SEED_CONFIDENCE = {\n",
" \"annual_contact_volume\": \"🟢 known\",\n",
" \"blended_cost_per_contact\": \"🟡 estimated\",\n",
" \"agent_headcount\": \"🟢 known\",\n",
" \"annual_attrition_rate\": \"🟡 estimated\",\n",
" \"current_containment_rate\": \"🟡 estimated\",\n",
" \"average_handle_time_seconds\": \"🟢 known\",\n",
"}\n",
"# Seed capability profile: data_readiness is the unique weakest\n",
"# foundation, so the demo shows a single binding constraint.\n",
"SEED_SCORES = {\n",
" \"automation_ai_strategy\": (2, \"AI driven by board pressure; no written thesis\"),\n",
" \"value_realization\": (2, \"Business cases pre-investment only\"),\n",
" \"executive_alignment\": (3, \"COO owns CX AI; steering meets quarterly\"),\n",
" \"process_discovery\": (3, \"Top 10 call reasons mapped with volumes\"),\n",
" \"data_readiness\": (2, \"KB stale; interaction data siloed in recordings\"),\n",
" \"technical_architecture\": (3, \"CCaaS APIs available; shared integration layer WIP\"),\n",
" \"use_case_prioritization\": (3, \"Scored backlog reviewed monthly\"),\n",
" \"delivery_capability\": (3, \"Two bots in production via SI partner\"),\n",
" \"talent_and_skills\": (2, \"One conversation designer, contractor\"),\n",
" \"ai_operations\": (2, \"Containment eyeballed weekly, no drift alerts\"),\n",
" \"change_adoption\": (3, \"Agent champions for copilot rollout\"),\n",
" \"governance_and_risk\": (3, \"AI policy signed; review board for voice bots\"),\n",
"}\n",
"# label, min, max, step per baseline field (explicit min/max — Pattern §3).\n",
"BASELINE_META = {\n",
" \"annual_contact_volume\": (\"Annual contact volume\", 0, 100_000_000, 10_000),\n",
" \"blended_cost_per_contact\": (\"Blended cost per contact ($)\", 0, 100, 0.25),\n",
" \"agent_headcount\": (\"Agent headcount\", 0, 100_000, 10),\n",
" \"annual_attrition_rate\": (\"Annual attrition rate (0-1)\", 0, 1, 0.01),\n",
" \"current_containment_rate\": (\"Current containment rate (0-1)\", 0, 1, 0.01),\n",
" \"average_handle_time_seconds\": (\"Average handle time (seconds)\", 0, 3600, 10),\n",
"}\n",
"\n",
"backstage(f\"diaglib loaded — {len(COMPETENCIES)} competencies · \"\n",
" f\"industries: {', '.join(INDUSTRIES)}\")"
]
},
{
"cell_type": "markdown",
"id": "bbfd8baf",
"metadata": {},
"source": [
"## How to run this session\n",
"\n",
"- **Sidebar §1 — Engagement.** Client, industry config, date, participants\n",
" (`Name | Role | Function` separated by `;` — functions: cx, it, ops,\n",
" finance, other), and a running notes box.\n",
"- **Sidebar §2 — Operational baseline.** Six numbers. If unknown, best\n",
" estimate is fine — set the confidence flag and the analysis will carry\n",
" the uncertainty explicitly.\n",
"- **Sidebar §3 — Capability scoring.** Pick **Now scoring**, read the\n",
" competency card on stage with the room, set the 15 slider, capture one\n",
" line of evidence, move to the next. The heatmap and value analysis\n",
" update live as you go.\n",
"- **Export.** The button at the bottom of the page writes\n",
" `exports/{engagement_id}.json` (source of truth) and `.csv` (flat\n",
" scores) — a deliberate snapshot at click time.\n",
"- **Backstage** (JupyterLab / nbconvert) — the verification gate and the\n",
" machine-readable appendix; neither shows on the Mercury stage."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "6393a965",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:37.880508Z",
"iopub.status.busy": "2026-07-19T23:45:37.880214Z",
"iopub.status.idle": "2026-07-19T23:45:37.904951Z",
"shell.execute_reply": "2026-07-19T23:45:37.904267Z"
}
},
"outputs": [
{
"data": {
"application/mercury+json": {
"model_id": "5feaf4858ee043a8b09f3507ce84f49c",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "5feaf4858ee043a8b09f3507ce84f49c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "ff4373a0dfc347d09f933f0e101f3243",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "ff4373a0dfc347d09f933f0e101f3243",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80ec0440>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "bae59fd8c40a4e16bde1f847d17c7192",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "bae59fd8c40a4e16bde1f847d17c7192",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80ec0590>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "2782d2713dfc449aaa69d11007cace4e",
"position": "sidebar",
"widget": "DateInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "2782d2713dfc449aaa69d11007cace4e",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.date.DateInputWidget object at 0x72cd80ec0830>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "955923ab919f4bce897169977d539ea5",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "955923ab919f4bce897169977d539ea5",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e22fd0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "d34dbe00c35d4eb6b8a7da2340dbe2e1",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "d34dbe00c35d4eb6b8a7da2340dbe2e1",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e23250>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "2ef89a29c65c4d978ec5ced9504dba73",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "2ef89a29c65c4d978ec5ced9504dba73",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e062c0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── 1 · Engagement setup (sidebar — widgets ONLY, no other output) ──\n",
"# Mercury re-runs only cells BELOW a changed widget: every .value is\n",
"# read in the state cell further down, never here (Pattern §3).\n",
"mr.Markdown(\"#### 1 · Engagement\", position=\"sidebar\")\n",
"_client_w = mr.TextInput(label=\"Client name\", value=SEED_CLIENT)\n",
"_industry_w = mr.Select(label=\"Industry config\", value=\"contact_center\",\n",
" choices=INDUSTRIES)\n",
"_date_w = mr.DateInput(label=\"Workshop date\", value=SEED_DATE)\n",
"_facilitator_w = mr.TextInput(label=\"Facilitator\", value=SEED_FACILITATOR)\n",
"_participants_w = mr.TextInput(\n",
" label=\"Participants — Name | Role | Function; ...\",\n",
" value=SEED_PARTICIPANTS)\n",
"_notes_w = mr.TextInput(label=\"Session notes\", value=\"\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "519ceb51",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:37.906389Z",
"iopub.status.busy": "2026-07-19T23:45:37.906260Z",
"iopub.status.idle": "2026-07-19T23:45:37.943107Z",
"shell.execute_reply": "2026-07-19T23:45:37.941718Z"
}
},
"outputs": [
{
"data": {
"application/mercury+json": {
"model_id": "0384abc193994b69881674157eb6b28f",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "0384abc193994b69881674157eb6b28f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "cc160d674e60481695cd07ca5098e1ca",
"position": "sidebar",
"widget": "NumberInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "cc160d674e60481695cd07ca5098e1ca",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.number.NumberInputWidget object at 0x72cdb76f4050>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "d59db85587a8467dae0addb485bc3cbc",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "d59db85587a8467dae0addb485bc3cbc",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80efe990>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "878ac4372b24422d9e06d9c6a77ed9b2",
"position": "sidebar",
"widget": "NumberInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "878ac4372b24422d9e06d9c6a77ed9b2",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.number.NumberInputWidget object at 0x72cd80efec10>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "956c843fdb3847f6a6e9e8f07824acb9",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "956c843fdb3847f6a6e9e8f07824acb9",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80efee90>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "facdfdd6c0494307b51225d81b78aad8",
"position": "sidebar",
"widget": "NumberInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "facdfdd6c0494307b51225d81b78aad8",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.number.NumberInputWidget object at 0x72cd80eff110>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "9c7d24f3d7b64b3e858baaa83002d48d",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "9c7d24f3d7b64b3e858baaa83002d48d",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80e07ce0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "8843aabb37b748a78228f4b18c49e6aa",
"position": "sidebar",
"widget": "NumberInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "8843aabb37b748a78228f4b18c49e6aa",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.number.NumberInputWidget object at 0x72cd80e6c180>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "ec1d09aab4cd43d7821005f37d7acd59",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "ec1d09aab4cd43d7821005f37d7acd59",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80e6c2b0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "90d4dc2d15514ebda566e852ce78bf73",
"position": "sidebar",
"widget": "NumberInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "90d4dc2d15514ebda566e852ce78bf73",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.number.NumberInputWidget object at 0x72cd80e6c3e0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "c82b1adbfcd44ff88abd892f4fd78301",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "c82b1adbfcd44ff88abd892f4fd78301",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80e7da30>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "60fabcff9f5e4a37942bb364eccddb85",
"position": "sidebar",
"widget": "NumberInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "60fabcff9f5e4a37942bb364eccddb85",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.number.NumberInputWidget object at 0x72cd80e7dc70>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "780c3efc5ec54ecc9ea40ce81f52cc28",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "780c3efc5ec54ecc9ea40ce81f52cc28",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80e978a0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── 2 · Operational baseline (sidebar — widgets ONLY) ───────────────\n",
"# Six numbers + a confidence flag each. Explicit min/max on every\n",
"# NumberInput — Mercury clamps out-of-range seeds to a default range.\n",
"mr.Markdown(\"#### 2 · Operational baseline\", position=\"sidebar\")\n",
"_baseline_w, _conf_w = {}, {}\n",
"for _f in BASELINE_FIELDS:\n",
" _label, _min, _max, _step = BASELINE_META[_f]\n",
" _baseline_w[_f] = mr.NumberInput(label=_label, value=SEED_BASELINE[_f],\n",
" min=_min, max=_max, step=_step)\n",
" _conf_w[_f] = mr.Select(label=f\"{_label} — confidence\",\n",
" value=SEED_CONFIDENCE[_f],\n",
" choices=CONFIDENCE_CHOICES)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "53450686",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:37.944822Z",
"iopub.status.busy": "2026-07-19T23:45:37.944677Z",
"iopub.status.idle": "2026-07-19T23:45:38.038687Z",
"shell.execute_reply": "2026-07-19T23:45:38.037711Z"
}
},
"outputs": [
{
"data": {
"application/mercury+json": {
"model_id": "4bbea152c5354344bad9cae9ae4b131f",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "4bbea152c5354344bad9cae9ae4b131f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "0134ad746d16416390a46248fe5e1aa3",
"position": "sidebar",
"widget": "SelectWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "0134ad746d16416390a46248fe5e1aa3",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.select.SelectWidget object at 0x72cd80e979b0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "9ede9faa5bc44112a30d3093c7709cbc",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "9ede9faa5bc44112a30d3093c7709cbc",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "8eaaa94d855d4747afed128c16d66308",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "8eaaa94d855d4747afed128c16d66308",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cdb76f01a0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "eecaf52a0a074f02a04efd099b4f22d9",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "eecaf52a0a074f02a04efd099b4f22d9",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e6f100>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "d48a2c7bbda8440aa87e9078553f38e9",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "d48a2c7bbda8440aa87e9078553f38e9",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80effb10>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "1dd77bf8ef284086a98c3f506dac122d",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "1dd77bf8ef284086a98c3f506dac122d",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e7deb0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "738b9403a2cb4d3498f2e174430c6d5b",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "738b9403a2cb4d3498f2e174430c6d5b",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80effed0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "bdf928b007aa4132aefb644a6b6c751b",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "bdf928b007aa4132aefb644a6b6c751b",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80d1c380>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "114ea157213646ccba3e4a6ea52c2856",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "114ea157213646ccba3e4a6ea52c2856",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "39ce7dffb71b41b7a2d6f14e63b2ad15",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "39ce7dffb71b41b7a2d6f14e63b2ad15",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80d35f30>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "96a1888c76f24e1ebc7f86c991ada96e",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "96a1888c76f24e1ebc7f86c991ada96e",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80d1c490>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "5cc39b1eef054bc9a484708bbcf282ee",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "5cc39b1eef054bc9a484708bbcf282ee",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80d36060>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "c0def29eb51e47f78e0c2bd3db3afc0a",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "c0def29eb51e47f78e0c2bd3db3afc0a",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e9ed50>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "741f4d5aeaf34ea6bebbba0b72f23426",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "741f4d5aeaf34ea6bebbba0b72f23426",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80e7e0f0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "f0ead6ff95fd46d598e4b8cd15cce31d",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "f0ead6ff95fd46d598e4b8cd15cce31d",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80e9f050>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "a7000c769e234457a69473437aea7491",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "a7000c769e234457a69473437aea7491",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "45b419ade2d446f887aefbcc8167ba6a",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "45b419ade2d446f887aefbcc8167ba6a",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80e97f00>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "82b3e6f7ce29429b94f0beb47b226b59",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "82b3e6f7ce29429b94f0beb47b226b59",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80f9bc50>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "36927983549046499f7d080a20c1b0b8",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "36927983549046499f7d080a20c1b0b8",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80d1c050>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "e91abb56e78a484598c5d47806b26282",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "e91abb56e78a484598c5d47806b26282",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80f9be30>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "7aa2b22ed12d4c1a9ff00e2432464da8",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "7aa2b22ed12d4c1a9ff00e2432464da8",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80e9f550>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "8bb4e603517a49d7a9976ee555dff224",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "8bb4e603517a49d7a9976ee555dff224",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80ebf310>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "333656890d3a4dce8a18171604757325",
"position": "sidebar",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "333656890d3a4dce8a18171604757325",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "12b153c6fe8d4f7db07a58270abc11d8",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "12b153c6fe8d4f7db07a58270abc11d8",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80e9f750>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "33c48116b82842f8b1a571804a90ebca",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "33c48116b82842f8b1a571804a90ebca",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80ebea50>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "275ca35bfb974e3bab5d507f521fc4c2",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "275ca35bfb974e3bab5d507f521fc4c2",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80f9b6b0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "40697a7b3df442ffb315149b61aaa646",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "40697a7b3df442ffb315149b61aaa646",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80ea54a0>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "74ca96bfbd7a44c7a87eb3c1e0a895e0",
"position": "sidebar",
"widget": "SliderWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "74ca96bfbd7a44c7a87eb3c1e0a895e0",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.slider.SliderWidget object at 0x72cd80f9ba70>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/mercury+json": {
"model_id": "d7940b33fc6f484582428064dfc25d0d",
"position": "sidebar",
"widget": "TextInputWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "d7940b33fc6f484582428064dfc25d0d",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.text.TextInputWidget object at 0x72cd80f8f950>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── 3 · Capability scoring (sidebar — widgets ONLY) ─────────────────\n",
"# One screen per competency on stage: pick \"Now scoring\", read the card\n",
"# with the room, set the slider, capture one line of evidence. Labels\n",
"# are distinct per widget so Mercury's cache never collides.\n",
"mr.Markdown(\"#### 3 · Capability scoring\", position=\"sidebar\")\n",
"_now_scoring_w = mr.Select(\n",
" label=\"Now scoring\",\n",
" value=f\"1 · {COMPETENCIES[0].name}\",\n",
" choices=[f\"{_i + 1} · {_c.name}\" for _i, _c in enumerate(COMPETENCIES)])\n",
"_score_w, _evidence_w = {}, {}\n",
"_prev_dim = None\n",
"for _c in COMPETENCIES:\n",
" if _c.dimension != _prev_dim:\n",
" mr.Markdown(f\"**{DIMENSION_NAME[_c.dimension]}**\", position=\"sidebar\")\n",
" _prev_dim = _c.dimension\n",
" _score_w[_c.id] = mr.Slider(label=f\"Score — {_c.name}\",\n",
" min=1, max=5, value=SEED_SCORES[_c.id][0])\n",
" _evidence_w[_c.id] = mr.TextInput(label=f\"Evidence — {_c.name}\",\n",
" value=SEED_SCORES[_c.id][1])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "5e127edd",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:38.040813Z",
"iopub.status.busy": "2026-07-19T23:45:38.040663Z",
"iopub.status.idle": "2026-07-19T23:45:38.066837Z",
"shell.execute_reply": "2026-07-19T23:45:38.066033Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Value at stake: $2.5M-$5.1M theoretical per year · $950K-$3.1M realizable over 18 months — capped at level 2 by Data Readiness\n",
"engagement acme_demo_co_2026-07-19 · 2 participants · evidence 12/12\n"
]
}
],
"source": [
"# ── Session state (re-runs on any sidebar change) ───────────────────\n",
"# Read every widget .value; all computation happens in diaglib.\n",
"CLIENT_NAME = str(_client_w.value).strip() or SEED_CLIENT\n",
"INDUSTRY = str(_industry_w.value)\n",
"CONFIG = load_config(INDUSTRY, CONFIGS_DIR)\n",
"WORKSHOP_DATE = dt.date.fromisoformat(str(_date_w.value) or SEED_DATE)\n",
"PARTICIPANTS = parse_participants(str(_participants_w.value))\n",
"NOTES = str(_notes_w.value)\n",
"\n",
"_vals = {f: float(_baseline_w[f].value) for f in BASELINE_FIELDS}\n",
"BASELINE = OperationalBaseline(\n",
" annual_contact_volume=int(_vals[\"annual_contact_volume\"]),\n",
" blended_cost_per_contact=_vals[\"blended_cost_per_contact\"],\n",
" agent_headcount=int(_vals[\"agent_headcount\"]),\n",
" annual_attrition_rate=_vals[\"annual_attrition_rate\"],\n",
" current_containment_rate=_vals[\"current_containment_rate\"],\n",
" average_handle_time_seconds=int(_vals[\"average_handle_time_seconds\"]),\n",
" field_confidence={f: str(_conf_w[f].value).split()[-1]\n",
" for f in BASELINE_FIELDS},\n",
")\n",
"\n",
"RAW_SCORES = {c.id: (int(_score_w[c.id].value), str(_evidence_w[c.id].value))\n",
" for c in COMPETENCIES}\n",
"SCORES = build_scores(CONFIG, RAW_SCORES, scored_at=dt.datetime.now())\n",
"VAS = value_at_stake(CONFIG, BASELINE, SCORES)\n",
"ENGAGEMENT = build_engagement(\n",
" config=CONFIG, client_name=CLIENT_NAME,\n",
" facilitator=str(_facilitator_w.value), workshop_date=WORKSHOP_DATE,\n",
" participants=PARTICIPANTS, baseline=BASELINE, scores=SCORES,\n",
" computed_value=VAS, notes=NOTES)\n",
"\n",
"NOW_SCORING = COMPETENCIES[int(str(_now_scoring_w.value).split(\" · \")[0]) - 1]\n",
"_done, _total = evidence_coverage(SCORES)\n",
"\n",
"# One curated line on stage; warnings surface for the room; echo backstage.\n",
"if CONFIG.value_drivers:\n",
" _bind = \", \".join(CONFIG.competency(c).name for c in VAS.binding_constraints)\n",
" print(f\"Value at stake: {money(VAS.theoretical_annual_value_low)}-\"\n",
" f\"{money(VAS.theoretical_annual_value_high)} theoretical per year · \"\n",
" f\"{money(VAS.realizable_18mo_low)}-{money(VAS.realizable_18mo_high)} \"\n",
" f\"realizable over 18 months — capped at level \"\n",
" f\"{VAS.weakest_foundational_score} by {_bind}\")\n",
"for _warning in VAS.warnings:\n",
" print(f\"⚠ {_warning}\")\n",
"backstage(f\"engagement {ENGAGEMENT.engagement_id} · \"\n",
" f\"{len(PARTICIPANTS)} participants · evidence {_done}/{_total}\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "5c3959a5",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:38.069170Z",
"iopub.status.busy": "2026-07-19T23:45:38.068934Z",
"iopub.status.idle": "2026-07-19T23:45:38.082309Z",
"shell.execute_reply": "2026-07-19T23:45:38.081608Z"
}
},
"outputs": [
{
"data": {
"application/mercury+json": {
"model_id": "a76214e4ed5548de8e248286ea47d040",
"position": "inline",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "a76214e4ed5548de8e248286ea47d040",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── Stage: engagement banner + baseline echo ────────────────────────\n",
"_chips = \"\".join(\n",
" f'<span style=\"display:inline-block;border:1px solid {HAIRLINE};'\n",
" f'border-radius:14px;padding:2px 10px;margin:2px 6px 2px 0;'\n",
" f'font:12px {BODY_FONT};color:{MUTED}\">{esc(p.name)}'\n",
" + (f\" · {esc(p.role)}\" if p.role else \"\")\n",
" + f' <b style=\"color:{BLUE}\">{esc(p.function)}</b></span>'\n",
" for p in PARTICIPANTS) or (\n",
" f'<span style=\"font:13px {BODY_FONT};color:{MUTED}\">'\n",
" f'no participants captured yet</span>')\n",
"\n",
"_rows = \"\"\n",
"for _f in BASELINE_FIELDS:\n",
" _v = getattr(BASELINE, _f)\n",
" _shown = f\"{_v:,.2f}\" if isinstance(_v, float) and _v < 10 else f\"{_v:,.0f}\"\n",
" _rows += (\n",
" f'<tr><td style=\"padding:3px 14px 3px 0;font:13px {BODY_FONT};'\n",
" f'color:{MUTED}\">{BASELINE_META[_f][0]}</td>'\n",
" f'<td style=\"padding:3px 10px;font:600 13px {BODY_FONT};color:{INK};'\n",
" f'text-align:right\">{_shown}</td>'\n",
" f'<td style=\"padding:3px 0\">{CONFIDENCE_ICON[BASELINE.confidence_for(_f)]}'\n",
" f'</td></tr>')\n",
"\n",
"_ = mr.Markdown(text=(\n",
" f'<div style=\"max-width:860px\">'\n",
" f'<div style=\"font:700 24px {FONT};color:{NAVY};margin:4px 0 2px\">'\n",
" f'{esc(CLIENT_NAME)} — CX AI Diagnostic</div>'\n",
" f'<div style=\"font:14px {BODY_FONT};color:{MUTED};margin-bottom:8px\">'\n",
" f'{esc(CONFIG.display_name)} · {WORKSHOP_DATE.isoformat()} · '\n",
" f'facilitated by {esc(ENGAGEMENT.facilitator)} · '\n",
" f'evidence captured {_done}/{_total}</div>'\n",
" f'<div style=\"margin:6px 0 10px\">{_chips}</div>'\n",
" f'<div style=\"border:1px solid {HAIRLINE};border-radius:10px;'\n",
" f'background:{CARD_BG};padding:10px 16px;display:inline-block\">'\n",
" f'<div style=\"font:700 13px {FONT};color:{NAVY};margin-bottom:4px\">'\n",
" f'Operational baseline</div>'\n",
" f'<table style=\"border-collapse:collapse\">{_rows}</table></div></div>'))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0807c87c",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:38.084220Z",
"iopub.status.busy": "2026-07-19T23:45:38.084075Z",
"iopub.status.idle": "2026-07-19T23:45:38.097120Z",
"shell.execute_reply": "2026-07-19T23:45:38.094011Z"
}
},
"outputs": [
{
"data": {
"application/mercury+json": {
"model_id": "a57e5835f51a4a0ea099d86287ba82bf",
"position": "inline",
"widget": "MarkdownWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "a57e5835f51a4a0ea099d86287ba82bf",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"MarkdownWidget(value='<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, \\'Segoe UI\\', Roboto, …"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── Stage: the scoring screen (one competency at a time) ────────────\n",
"_c = NOW_SCORING\n",
"_score, _evidence = RAW_SCORES[_c.id]\n",
"\n",
"# Progress strip: one box per competency — its current score, solid\n",
"# border once evidence is captured, highlighted while on screen.\n",
"_boxes = \"\"\n",
"for _i, _cc in enumerate(COMPETENCIES):\n",
" _s, _e = RAW_SCORES[_cc.id]\n",
" _bg = HILITE if _cc.id == _c.id else CARD_BG\n",
" _border = f\"1px solid {HAIRLINE}\" if not _e else f\"1px solid {MUTED}\"\n",
" if _cc.id == _c.id:\n",
" _border = f\"2px solid {BLUE}\"\n",
" _boxes += (\n",
" f'<span title=\"{esc(_cc.name)}\" style=\"display:inline-block;'\n",
" f'width:30px;height:30px;line-height:28px;text-align:center;'\n",
" f'border:{_border};border-radius:6px;background:{_bg};'\n",
" f'font:600 14px {BODY_FONT};color:{INK};margin-right:5px\">{_s}</span>')\n",
"\n",
"_levels = \"\"\n",
"for _lvl in range(1, 6):\n",
" _sel = _lvl == _score\n",
" _levels += (\n",
" f'<tr><td style=\"padding:5px 12px;font:700 14px {BODY_FONT};'\n",
" f'color:{BLUE if _sel else MUTED};border-left:4px solid '\n",
" f'{BLUE if _sel else \"transparent\"};background:'\n",
" f'{HILITE if _sel else \"transparent\"}\">{_lvl}</td>'\n",
" f'<td style=\"padding:5px 8px;font:{\"600 \" if _sel else \"\"}14px '\n",
" f'{BODY_FONT};color:{INK if _sel else MUTED};background:'\n",
" f'{HILITE if _sel else \"transparent\"}\">'\n",
" f'{esc(_c.level_descriptors[_lvl])}</td></tr>')\n",
"\n",
"_evidence_html = (\n",
" f'<span style=\"color:{GREEN}\">✓</span> {esc(_evidence)}' if _evidence\n",
" else f'<span style=\"color:{MUTED}\">no evidence captured yet — '\n",
" f'one line: what makes this a level {_score}?</span>')\n",
"\n",
"_ = mr.Markdown(text=(\n",
" f'<div style=\"max-width:860px\">'\n",
" f'<div style=\"margin:14px 0 8px\">{_boxes}</div>'\n",
" f'<div style=\"border:1px solid {HAIRLINE};border-radius:10px;'\n",
" f'background:#ffffff;padding:16px 20px\">'\n",
" f'<div style=\"font:600 12px {BODY_FONT};color:{BLUE};'\n",
" f'text-transform:uppercase;letter-spacing:.06em\">'\n",
" f'{DIMENSION_NAME[_c.dimension]}</div>'\n",
" f'<div style=\"font:700 21px {FONT};color:{NAVY};margin:2px 0 6px\">'\n",
" f'{esc(_c.name)}</div>'\n",
" f'<div style=\"font:15px {BODY_FONT};color:{INK};margin-bottom:6px\">'\n",
" f'{esc(_c.description)}</div>'\n",
" f'<div style=\"font:italic 14px {FONT};color:{MUTED};margin-bottom:10px\">'\n",
" f'\"{esc(_c.failure_vignette)}\"</div>'\n",
" f'<table style=\"border-collapse:collapse;width:100%\">{_levels}</table>'\n",
" f'<div style=\"font:13px {BODY_FONT};color:{INK};margin-top:10px;'\n",
" f'border-top:1px solid {LINE};padding-top:8px\">'\n",
" f'<b>Evidence:</b> {_evidence_html}</div>'\n",
" f'</div></div>'))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "fd7ee43b",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:38.099790Z",
"iopub.status.busy": "2026-07-19T23:45:38.099524Z",
"iopub.status.idle": "2026-07-19T23:45:39.732315Z",
"shell.execute_reply": "2026-07-19T23:45:39.729895Z"
}
},
"outputs": [
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"colorscale": [
[
0.0,
"#ef8a76"
],
[
0.5,
"#f0efe9"
],
[
1.0,
"#57c993"
]
],
"customdata": [
[
"<b>Automation & AI Strategy</b> — level 2<br>Aspirational vision, no operating model implications defined.<br><i>AI driven by board pressure; no written thesis</i>",
"<b>Value Realization</b> — level 2<br>Business cases exist pre-investment; nobody measures after go-live.<br><i>Business cases pre-investment only</i>",
"<b>Executive Alignment</b> — level 3<br>Named executive owner; cross-functional steering exists on paper.<br><i>COO owns CX AI; steering meets quarterly</i>"
],
[
"<b>Process Discovery</b> — level 3<br>Priority journeys mapped at task level with volumes and handle data.<br><i>Top 10 call reasons mapped with volumes</i>",
"<b>Data Readiness</b> — level 2<br>Key sources identified; access is manual and quality unknown.<br><i>KB stale; interaction data siloed in recordings</i>",
"<b>Technical Architecture</b> — level 3<br>Reference architecture defined; shared integration layer for priority systems.<br><i>CCaaS APIs available; shared integration layer WIP</i>"
],
[
"<b>Use Case Prioritization</b> — level 3<br>Value and feasibility scoring; a prioritized backlog is reviewed.<br><i>Scored backlog reviewed monthly</i>",
"<b>Delivery Capability</b> — level 3<br>A standard delivery path exists; a few use cases run in production.<br><i>Two bots in production via SI partner</i>",
"<b>Talent & Skills</b> — level 2<br>Isolated enthusiasts self-teach; no roles or paths defined.<br><i>One conversation designer, contractor</i>"
],
[
"<b>AI Operations</b> — level 2<br>Manual spot checks; tuning happens when someone escalates.<br><i>Containment eyeballed weekly, no drift alerts</i>",
"<b>Change & Adoption</b> — level 3<br>Structured change program for major rollouts; adoption tracked.<br><i>Agent champions for copilot rollout</i>",
"<b>Governance & Risk</b> — level 3<br>AI policy and a review board for high-risk use cases.<br><i>AI policy signed; review board for voice bots</i>"
]
],
"hovertemplate": "%{customdata}<extra></extra>",
"showscale": false,
"text": [
[
"2<br>Automation & AI Strategy",
"2<br>Value Realization",
"3<br>Executive Alignment"
],
[
"3<br>Process Discovery",
"2<br>Data Readiness",
"3<br>Technical Architecture"
],
[
"3<br>Use Case Prioritization",
"3<br>Delivery Capability",
"2<br>Talent & Skills"
],
[
"2<br>AI Operations",
"3<br>Change & Adoption",
"3<br>Governance & Risk"
]
],
"textfont": {
"color": "#0b0b0b",
"size": 13
},
"texttemplate": "%{text}",
"type": "heatmap",
"x": [
0,
1,
2
],
"xgap": 3,
"y": [
"Strategy & Value",
"Foundations",
"Delivery",
"Sustain"
],
"ygap": 3,
"z": [
[
2,
2,
3
],
[
3,
2,
3
],
[
3,
3,
2
],
[
2,
3,
3
]
],
"zmax": 5,
"zmin": 1
}
],
"layout": {
"font": {
"color": "#52514e",
"family": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
"size": 13
},
"height": 480,
"legend": {
"font": {
"color": "#52514e",
"size": 11
},
"orientation": "h",
"x": 0,
"y": -0.12,
"yanchor": "top"
},
"margin": {
"b": 60,
"l": 70,
"r": 30,
"t": 70
},
"paper_bgcolor": "#fcfcfb",
"plot_bgcolor": "#fcfcfb",
"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.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.0,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "heatmap"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#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.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.0,
"#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.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.0,
"#f0f921"
]
],
"sequentialminus": [
[
0.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.0,
"#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": {
"font": {
"color": "#0b0b0b",
"size": 16
},
"text": "<b>Capability heatmap</b><br><span style='font-size:12px;color:#898781'>12 competencies, levels 15 · hover a cell for the evidence</span>",
"x": 0.02,
"xanchor": "left"
},
"xaxis": {
"visible": false
},
"yaxis": {
"autorange": "reversed",
"showgrid": false,
"tickfont": {
"color": "#52514e",
"size": 13
}
}
}
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"base": [
2542500.0
],
"hovertemplate": "Theoretical value (annual): &#36;2.5M &#36;5.1M<extra></extra>",
"marker": {
"color": "#9ec5f4",
"line": {
"color": "#fcfcfb",
"width": 2
}
},
"orientation": "h",
"showlegend": false,
"type": "bar",
"x": [
2542500.0
],
"y": [
"Theoretical value (annual)"
]
},
{
"base": [
953437.5
],
"hovertemplate": "Realizable over 18 months: &#36;950K &#36;3.1M<extra></extra>",
"marker": {
"color": "#2a78d6",
"line": {
"color": "#fcfcfb",
"width": 2
}
},
"orientation": "h",
"showlegend": false,
"type": "bar",
"x": [
2097562.5
],
"y": [
"Realizable over 18 months"
]
}
],
"layout": {
"annotations": [
{
"font": {
"color": "#0b0b0b",
"size": 12
},
"showarrow": false,
"text": "&#36;2.5M &#36;5.1M",
"x": 5085000.0,
"xanchor": "left",
"xshift": 6,
"y": "Theoretical value (annual)"
},
{
"font": {
"color": "#0b0b0b",
"size": 12
},
"showarrow": false,
"text": "&#36;950K &#36;3.1M",
"x": 3051000.0,
"xanchor": "left",
"xshift": 6,
"y": "Realizable over 18 months"
},
{
"align": "left",
"font": {
"color": "#0b0b0b",
"size": 13
},
"showarrow": false,
"text": "Trapped by the capability gap: <b>&#36;1.5M &#36;3.8M</b> per year",
"x": 0.02,
"xanchor": "left",
"xref": "paper",
"y": -0.32,
"yref": "paper"
}
],
"bargap": 0.5,
"font": {
"color": "#52514e",
"family": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
"size": 13
},
"height": 300,
"legend": {
"font": {
"color": "#52514e",
"size": 11
},
"orientation": "h",
"x": 0,
"y": -0.12,
"yanchor": "top"
},
"margin": {
"b": 90,
"l": 70,
"r": 30,
"t": 70
},
"paper_bgcolor": "#fcfcfb",
"plot_bgcolor": "#fcfcfb",
"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.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.0,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "heatmap"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#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.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.0,
"#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.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.0,
"#f0f921"
]
],
"sequentialminus": [
[
0.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.0,
"#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": {
"font": {
"color": "#0b0b0b",
"size": 16
},
"text": "<b>Value at stake</b><br><span style='font-size:12px;color:#898781'>ranges, never points · realization capped by the weakest foundation</span>",
"x": 0.02,
"xanchor": "left"
},
"xaxis": {
"gridcolor": "#e1e0d9",
"rangemode": "tozero",
"tickfont": {
"color": "#898781"
},
"tickformat": "$~s",
"zeroline": false
},
"yaxis": {
"autorange": "reversed",
"showgrid": false,
"tickfont": {
"color": "#52514e",
"size": 13
}
}
}
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"hovertemplate": "Realizable: %{x:$,.0f}<extra>%{y}</extra>",
"insidetextfont": {
"color": "#ffffff"
},
"marker": {
"color": "#2a78d6",
"line": {
"color": "#fcfcfb",
"width": 2
}
},
"name": "Realizable (annual run-rate)",
"orientation": "h",
"text": [
"&#36;640K",
"&#36;2.0M"
],
"textposition": "inside",
"type": "bar",
"x": [
635625.0,
2034000.0
],
"y": [
"Conservative",
"Optimistic"
]
},
{
"hovertemplate": "Trapped: %{x:$,.0f}<extra>%{y}</extra>",
"insidetextfont": {
"color": "#0b0b0b"
},
"marker": {
"color": "#eda100",
"line": {
"color": "#fcfcfb",
"width": 2
}
},
"name": "Trapped by capability gap",
"orientation": "h",
"text": [
"&#36;1.9M",
"&#36;3.1M"
],
"textposition": "inside",
"type": "bar",
"x": [
1906875.0,
3051000.0
],
"y": [
"Conservative",
"Optimistic"
]
}
],
"layout": {
"bargap": 0.5,
"barmode": "stack",
"font": {
"color": "#52514e",
"family": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
"size": 13
},
"height": 300,
"legend": {
"font": {
"color": "#52514e",
"size": 11
},
"orientation": "h",
"traceorder": "normal",
"x": 0,
"y": -0.12,
"yanchor": "top"
},
"margin": {
"b": 60,
"l": 70,
"r": 30,
"t": 70
},
"paper_bgcolor": "#fcfcfb",
"plot_bgcolor": "#fcfcfb",
"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.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.0,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "heatmap"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#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.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.0,
"#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.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.0,
"#f0f921"
]
],
"sequentialminus": [
[
0.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.0,
"#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": {
"font": {
"color": "#0b0b0b",
"size": 16
},
"text": "<b>Where the annual value goes</b><br><span style='font-size:12px;color:#898781'>each scenario splits its own theoretical total</span>",
"x": 0.02,
"xanchor": "left"
},
"xaxis": {
"gridcolor": "#e1e0d9",
"tickfont": {
"color": "#898781"
},
"tickformat": "$~s",
"zeroline": false
},
"yaxis": {
"autorange": "reversed",
"showgrid": false,
"tickfont": {
"color": "#52514e",
"size": 13
}
}
}
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"base": [
300000.0,
800000.0,
1050000.0
],
"customdata": [
[
"Data Readiness",
"&#36;300K &#36;600K"
],
[
"Process Discovery + Data Readiness + Technical Architecture",
"&#36;800K &#36;1.6M"
],
[
"Process Discovery + Data Readiness + Technical Architecture",
"&#36;1.0M &#36;2.1M"
]
],
"hovertemplate": "%{customdata[0]}<br>Investment: %{customdata[1]}<extra></extra>",
"marker": {
"color": "#e34948",
"line": {
"color": "#fcfcfb",
"width": 2
}
},
"name": "Investment (range)",
"type": "bar",
"x": [
"<b>1 · Data Readiness</b><br>level 2 → 3",
"<b>2 · joint lift ×3</b><br>level 3 → 4",
"<b>3 · joint lift ×3</b><br>level 4 → 5"
],
"y": [
300000.0,
800000.0,
1050000.0
]
},
{
"base": [
635625.0,
381375.00000000006,
381375.00000000006
],
"customdata": [
[
"Data Readiness",
"&#36;640K &#36;1.3M"
],
[
"Process Discovery + Data Readiness + Technical Architecture",
"&#36;380K &#36;1.0M"
],
[
"Process Discovery + Data Readiness + Technical Architecture",
"&#36;380K &#36;760K"
]
],
"hovertemplate": "%{customdata[0]}<br>Unlocked: %{customdata[1]}<extra></extra>",
"marker": {
"color": "#1baf7a",
"line": {
"color": "#fcfcfb",
"width": 2
}
},
"name": "Annual value unlocked (range)",
"type": "bar",
"x": [
"<b>1 · Data Readiness</b><br>level 2 → 3",
"<b>2 · joint lift ×3</b><br>level 3 → 4",
"<b>3 · joint lift ×3</b><br>level 4 → 5"
],
"y": [
635625.0,
635624.9999999998,
381375.00000000006
]
}
],
"layout": {
"bargap": 0.35,
"bargroupgap": 0.12,
"barmode": "group",
"font": {
"color": "#52514e",
"family": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
"size": 13
},
"height": 420,
"legend": {
"font": {
"color": "#52514e",
"size": 11
},
"orientation": "h",
"x": 0,
"y": -0.12,
"yanchor": "top"
},
"margin": {
"b": 60,
"l": 70,
"r": 30,
"t": 70
},
"paper_bgcolor": "#fcfcfb",
"plot_bgcolor": "#fcfcfb",
"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.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.0,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "heatmap"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0.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.0,
"#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.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.0,
"#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.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.0,
"#f0f921"
]
],
"sequentialminus": [
[
0.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.0,
"#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": {
"font": {
"color": "#0b0b0b",
"size": 16
},
"text": "<b>Unlock sequence</b><br><span style='font-size:12px;color:#898781'>sequential moves — each is the prerequisite of the next</span>",
"x": 0.02,
"xanchor": "left"
},
"xaxis": {
"showgrid": false,
"tickangle": 0,
"tickfont": {
"color": "#52514e",
"size": 12
}
},
"yaxis": {
"gridcolor": "#e1e0d9",
"tickfont": {
"color": "#898781"
},
"tickformat": "$~s",
"zerolinecolor": "#c3c2b7"
}
}
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style type=\"text/css\">\n",
"</style>\n",
"<table id=\"T_5693d\">\n",
" <thead>\n",
" <tr>\n",
" <th id=\"T_5693d_level0_col0\" class=\"col_heading level0 col0\" >Move</th>\n",
" <th id=\"T_5693d_level0_col1\" class=\"col_heading level0 col1\" >Competencies</th>\n",
" <th id=\"T_5693d_level0_col2\" class=\"col_heading level0 col2\" >Lift</th>\n",
" <th id=\"T_5693d_level0_col3\" class=\"col_heading level0 col3\" >Est. cost</th>\n",
" <th id=\"T_5693d_level0_col4\" class=\"col_heading level0 col4\" >Weeks</th>\n",
" <th id=\"T_5693d_level0_col5\" class=\"col_heading level0 col5\" >Annual value unlocked</th>\n",
" <th id=\"T_5693d_level0_col6\" class=\"col_heading level0 col6\" >Note</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td id=\"T_5693d_row0_col0\" class=\"data row0 col0\" >1</td>\n",
" <td id=\"T_5693d_row0_col1\" class=\"data row0 col1\" >Data Readiness</td>\n",
" <td id=\"T_5693d_row0_col2\" class=\"data row0 col2\" >2 → 3</td>\n",
" <td id=\"T_5693d_row0_col3\" class=\"data row0 col3\" >$300K $600K</td>\n",
" <td id=\"T_5693d_row0_col4\" class=\"data row0 col4\" >12</td>\n",
" <td id=\"T_5693d_row0_col5\" class=\"data row0 col5\" >$640K $1.3M</td>\n",
" <td id=\"T_5693d_row0_col6\" class=\"data row0 col6\" ></td>\n",
" </tr>\n",
" <tr>\n",
" <td id=\"T_5693d_row1_col0\" class=\"data row1 col0\" >2</td>\n",
" <td id=\"T_5693d_row1_col1\" class=\"data row1 col1\" >Process Discovery + Data Readiness + Technical Architecture</td>\n",
" <td id=\"T_5693d_row1_col2\" class=\"data row1 col2\" >3 → 4</td>\n",
" <td id=\"T_5693d_row1_col3\" class=\"data row1 col3\" >$800K $1.6M</td>\n",
" <td id=\"T_5693d_row1_col4\" class=\"data row1 col4\" >16</td>\n",
" <td id=\"T_5693d_row1_col5\" class=\"data row1 col5\" >$380K $1.0M</td>\n",
" <td id=\"T_5693d_row1_col6\" class=\"data row1 col6\" >joint lift — the tied competencies must move together to shift the cap</td>\n",
" </tr>\n",
" <tr>\n",
" <td id=\"T_5693d_row2_col0\" class=\"data row2 col0\" >3</td>\n",
" <td id=\"T_5693d_row2_col1\" class=\"data row2 col1\" >Process Discovery + Data Readiness + Technical Architecture</td>\n",
" <td id=\"T_5693d_row2_col2\" class=\"data row2 col2\" >4 → 5</td>\n",
" <td id=\"T_5693d_row2_col3\" class=\"data row2 col3\" >$1.0M $2.1M</td>\n",
" <td id=\"T_5693d_row2_col4\" class=\"data row2 col4\" >20</td>\n",
" <td id=\"T_5693d_row2_col5\" class=\"data row2 col5\" >$380K $760K</td>\n",
" <td id=\"T_5693d_row2_col6\" class=\"data row2 col6\" >joint lift — the tied competencies must move together to shift the cap</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n"
],
"text/plain": [
"<pandas.io.formats.style.Styler at 0x72cd7e824ad0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── Stage: live analysis & visuals ──────────────────────────────────\n",
"heatmap_fig(heatmap_grid(CONFIG, SCORES)).show()\n",
"\n",
"if CONFIG.value_drivers:\n",
" value_bands_fig(VAS).show()\n",
" split_fig(VAS).show()\n",
" unlock_fig(VAS, CONFIG).show()\n",
" # The unlock moves as a table — the room verifies numbers by\n",
" # reading them, not by trusting the bars.\n",
" UNLOCK_DF = pd.DataFrame([{\n",
" \"Move\": _i + 1,\n",
" \"Competencies\": \" + \".join(CONFIG.competency(c).name\n",
" for c in _m.competency_ids),\n",
" \"Lift\": f\"{_m.current_level} → {_m.target_level}\",\n",
" \"Est. cost\": (f\"{money(_m.est_cost_low)} {money(_m.est_cost_high)}\"\n",
" if _m.est_cost_low is not None else \"not configured\"),\n",
" \"Weeks\": _m.est_weeks if _m.est_weeks is not None else \"—\",\n",
" \"Annual value unlocked\": (f\"{money(_m.value_unlocked_low)} \"\n",
" f\"{money(_m.value_unlocked_high)}\"),\n",
" \"Note\": _m.note,\n",
" } for _i, _m in enumerate(VAS.unlock_sequence)])\n",
" display(UNLOCK_DF.style.hide(axis=\"index\"))\n",
"else:\n",
" _ = mr.Markdown(text=(\n",
" f'<div style=\"border:1px solid {HAIRLINE};border-radius:10px;'\n",
" f'background:{CARD_BG};padding:12px 16px;max-width:860px;'\n",
" f'font:14px {BODY_FONT};color:{MUTED}\">'\n",
" f'<b style=\"color:{INK}\">{esc(CONFIG.display_name)}</b> has no value '\n",
" f'drivers configured yet — capability scoring works normally, but '\n",
" f'value-at-stake needs drivers in '\n",
" f'<code>configs/{esc(INDUSTRY)}.yaml</code>.</div>'))"
]
},
{
"cell_type": "markdown",
"id": "13fc62dc",
"metadata": {},
"source": [
"## Export\n",
"\n",
"The button writes `exports/{engagement_id}.json` — the full engagement\n",
"record, the source-of-truth artifact — and `exports/{engagement_id}.csv`,\n",
"one row per competency for cross-engagement analysis. A **deliberate\n",
"snapshot**: it captures the state at click time; click again after\n",
"changes to refresh."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "c5270335",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:39.734876Z",
"iopub.status.busy": "2026-07-19T23:45:39.734657Z",
"iopub.status.idle": "2026-07-19T23:45:39.752517Z",
"shell.execute_reply": "2026-07-19T23:45:39.742714Z"
}
},
"outputs": [
{
"data": {
"application/mercury+json": {
"model_id": "a32316625a884fa5887079be7390601f",
"position": "inline",
"widget": "ButtonWidget"
},
"application/vnd.jupyter.widget-view+json": {
"model_id": "a32316625a884fa5887079be7390601f",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"<mercury.button.ButtonWidget object at 0x72cd7e824ec0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# ── Export trigger (widgets ONLY — the click is handled below) ──────\n",
"_export_w = mr.Button(label=\"Export JSON + CSV\", position=\"inline\")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "6102b26e",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:39.754715Z",
"iopub.status.busy": "2026-07-19T23:45:39.754547Z",
"iopub.status.idle": "2026-07-19T23:45:39.759379Z",
"shell.execute_reply": "2026-07-19T23:45:39.758332Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No export click this run — engagement exports come from the stage button; report sources from scripts/export_report.py.\n"
]
}
],
"source": [
"# ── Export on click — snapshot semantics ────────────────────────────\n",
"# Kernel globals persist across Mercury re-runs; the guard writes\n",
"# exactly once per click, at whatever state the cockpit showed then.\n",
"try:\n",
" _LAST_EXPORT_CLICKS\n",
"except NameError:\n",
" _LAST_EXPORT_CLICKS = 0\n",
"\n",
"if int(_export_w.n_clicks) > _LAST_EXPORT_CLICKS:\n",
" _json_path, _csv_path = write_exports(ENGAGEMENT, CONFIG, EXPORTS_DIR)\n",
" _LAST_EXPORT_CLICKS = int(_export_w.n_clicks)\n",
" print(f\"Exported {_json_path.name} + {_csv_path.name} → exports/\")\n",
"else:\n",
" backstage(\"No export click this run — engagement exports come from the \"\n",
" \"stage button; report sources from scripts/export_report.py.\")"
]
},
{
"cell_type": "markdown",
"id": "d7e31813",
"metadata": {},
"source": [
"## Verification & assertions\n",
"\n",
"Engine pins use the explicit seed scenario, independent of the sidebar,\n",
"so the gate tests `diaglib` + `configs/`, not the current session;\n",
"live-state pins are guarded so a facilitator moving a slider never\n",
"crashes the room; structural ties hold at **any** widget state. This\n",
"cell must pass under headless `nbconvert --execute` — it is the study's\n",
"smoke test. Output renders backstage only."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "783bee1d",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:39.761329Z",
"iopub.status.busy": "2026-07-19T23:45:39.761202Z",
"iopub.status.idle": "2026-07-19T23:45:39.788813Z",
"shell.execute_reply": "2026-07-19T23:45:39.788027Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"All assertions passed.\n"
]
}
],
"source": [
"# ── Verification gate — must pass under headless nbconvert ──────────\n",
"def _approx(got, want, tol=0.5):\n",
" assert abs(got - want) <= tol, f\"got {got:,.2f}, want {want:,.2f}\"\n",
"\n",
"\n",
"# Engine pins — EXPLICIT seed scenario, independent of widget state.\n",
"# Hand arithmetic in tests/test_value_math.py (same scenario).\n",
"_gate_cfg = load_config(\"contact_center\", CONFIGS_DIR)\n",
"_gate_baseline = OperationalBaseline(\n",
" annual_contact_volume=1_200_000, blended_cost_per_contact=6.50,\n",
" agent_headcount=450, annual_attrition_rate=0.30,\n",
" current_containment_rate=0.20, average_handle_time_seconds=420)\n",
"_gate_scores = build_scores(_gate_cfg, SEED_SCORES,\n",
" scored_at=dt.datetime(2026, 7, 19, 9, 0))\n",
"_gate_vas = value_at_stake(_gate_cfg, _gate_baseline, _gate_scores)\n",
"_approx(_gate_vas.theoretical_annual_value_low, 2_542_500)\n",
"_approx(_gate_vas.theoretical_annual_value_high, 5_085_000)\n",
"_approx(_gate_vas.realizable_18mo_low, 953_437.50)\n",
"_approx(_gate_vas.realizable_18mo_high, 3_051_000)\n",
"_approx(_gate_vas.trapped_value_low, 1_525_500)\n",
"_approx(_gate_vas.trapped_value_high, 3_813_750)\n",
"assert _gate_vas.binding_constraints == [\"data_readiness\"]\n",
"assert len(_gate_vas.unlock_sequence) == 3\n",
"_m1 = _gate_vas.unlock_sequence[0]\n",
"assert _m1.competency_ids == [\"data_readiness\"]\n",
"assert (_m1.est_cost_low, _m1.est_cost_high, _m1.est_weeks) == (300_000, 600_000, 12)\n",
"_approx(_m1.value_unlocked_low, 635_625)\n",
"_approx(_m1.value_unlocked_high, 1_271_250)\n",
"\n",
"# Live-state pins — guarded, so a moved slider can't crash the room.\n",
"_at_default = (\n",
" INDUSTRY == \"contact_center\"\n",
" and all(getattr(BASELINE, f) == getattr(_gate_baseline, f)\n",
" for f in BASELINE_FIELDS)\n",
" and all(RAW_SCORES[k][0] == SEED_SCORES[k][0] for k in SEED_SCORES))\n",
"if _at_default:\n",
" _approx(VAS.theoretical_annual_value_low, 2_542_500)\n",
" _approx(VAS.realizable_18mo_high, 3_051_000)\n",
" _approx(VAS.trapped_value_high, 3_813_750)\n",
"\n",
"# Structural ties — hold at ANY widget state.\n",
"assert len(SCORES) == 12 and len({s.competency_id for s in SCORES}) == 12\n",
"assert VAS.theoretical_annual_value_low <= VAS.theoretical_annual_value_high\n",
"assert VAS.realizable_18mo_low <= VAS.realizable_18mo_high\n",
"assert VAS.trapped_value_low <= VAS.trapped_value_high\n",
"_approx(sum(d.theoretical_low for d in VAS.driver_values),\n",
" VAS.theoretical_annual_value_low)\n",
"_approx(sum(d.theoretical_high for d in VAS.driver_values),\n",
" VAS.theoretical_annual_value_high)\n",
"_approx(VAS.realizable_18mo_low,\n",
" VAS.theoretical_annual_value_low * VAS.realization_factor_low * 1.5)\n",
"_approx(VAS.realizable_18mo_high,\n",
" VAS.theoretical_annual_value_high * VAS.realization_factor_high * 1.5)\n",
"assert set(VAS.binding_constraints) <= set(CONFIG.foundational_competencies)\n",
"assert len(VAS.unlock_sequence) <= 3\n",
"\n",
"# Export payload is serializable and matches the live session.\n",
"import json as _json\n",
"_payload = _json.loads(engagement_json(ENGAGEMENT))\n",
"assert _payload[\"engagement_id\"] == ENGAGEMENT.engagement_id\n",
"assert len(_payload[\"scores\"]) == 12\n",
"_df = scores_dataframe(ENGAGEMENT, CONFIG)\n",
"assert list(_df.columns) == CSV_COLUMNS and len(_df) == 12\n",
"\n",
"backstage(\"All assertions passed.\")"
]
},
{
"cell_type": "markdown",
"id": "1913a663",
"metadata": {},
"source": [
"## Data appendix — for the machines\n",
"\n",
"The full engagement as markdown tables plus one JSON block of state, so\n",
"the exported report is complete LLM input — and the future Athena\n",
"study-export payload. Renders **backstage** — hidden on the Mercury\n",
"stage."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "4451b2fe",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:39.791499Z",
"iopub.status.busy": "2026-07-19T23:45:39.791353Z",
"iopub.status.idle": "2026-07-19T23:45:39.798212Z",
"shell.execute_reply": "2026-07-19T23:45:39.797618Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"#### Capability scores\n",
"\n",
"| Competency | Dimension | Score | Evidence |\n",
"|---|---|---:|---|\n",
"| Automation & AI Strategy | Strategy & Value | 2 | AI driven by board pressure; no written thesis |\n",
"| Value Realization | Strategy & Value | 2 | Business cases pre-investment only |\n",
"| Executive Alignment | Strategy & Value | 3 | COO owns CX AI; steering meets quarterly |\n",
"| Process Discovery | Foundations | 3 | Top 10 call reasons mapped with volumes |\n",
"| Data Readiness | Foundations | 2 | KB stale; interaction data siloed in recordings |\n",
"| Technical Architecture | Foundations | 3 | CCaaS APIs available; shared integration layer WIP |\n",
"| Use Case Prioritization | Delivery | 3 | Scored backlog reviewed monthly |\n",
"| Delivery Capability | Delivery | 3 | Two bots in production via SI partner |\n",
"| Talent & Skills | Delivery | 2 | One conversation designer, contractor |\n",
"| AI Operations | Sustain | 2 | Containment eyeballed weekly, no drift alerts |\n",
"| Change & Adoption | Sustain | 3 | Agent champions for copilot rollout |\n",
"| Governance & Risk | Sustain | 3 | AI policy signed; review board for voice bots |\n",
"\n",
"#### Dimension rollup\n",
"\n",
"| Dimension | Mean score |\n",
"|---|---:|\n",
"| Strategy & Value | 2.33 |\n",
"| Foundations | 2.67 |\n",
"| Delivery | 2.67 |\n",
"| Sustain | 2.67 |\n",
"\n",
"#### Value drivers (theoretical annual)\n",
"\n",
"| Driver | Low | High |\n",
"|---|---:|---:|\n",
"| Deflection / containment improvement | $1.2M | $2.7M |\n",
"| Average handle time reduction | $1.2M | $2.0M |\n",
"| Attrition reduction | $200K | $400K |\n",
"| **Total** | **$2.5M** | **$5.1M** |\n",
"\n",
"Realization band at weakest foundation level 2: 25%-40% · realizable 18-mo $950K-$3.1M · trapped $1.5M-$3.8M per year · binding: data_readiness\n",
"\n",
"#### Engagement state (JSON)\n",
"\n",
"```json\n",
"{\n",
" \"engagement_id\": \"acme_demo_co_2026-07-19\",\n",
" \"client_name\": \"Acme Demo Co\",\n",
" \"industry_config\": \"contact_center\",\n",
" \"facilitator\": \"Robert Helewka\",\n",
" \"workshop_date\": \"2026-07-19\",\n",
" \"participants\": [\n",
" {\n",
" \"name\": \"Jane Example\",\n",
" \"role\": \"VP Customer Experience\",\n",
" \"function\": \"cx\"\n",
" },\n",
" {\n",
" \"name\": \"Sam Sample\",\n",
" \"role\": \"Contact Center Ops Director\",\n",
" \"function\": \"ops\"\n",
" }\n",
" ],\n",
" \"operational_baseline\": {\n",
" \"annual_contact_volume\": 1200000,\n",
" \"blended_cost_per_contact\": 6.5,\n",
" \"agent_headcount\": 450,\n",
" \"annual_attrition_rate\": 0.3,\n",
" \"current_containment_rate\": 0.2,\n",
" \"average_handle_time_seconds\": 420,\n",
" \"csat_baseline\": null,\n",
" \"revenue_at_risk\": null,\n",
" \"field_confidence\": {\n",
" \"annual_contact_volume\": \"known\",\n",
" \"blended_cost_per_contact\": \"estimated\",\n",
" \"agent_headcount\": \"known\",\n",
" \"annual_attrition_rate\": \"estimated\",\n",
" \"current_containment_rate\": \"estimated\",\n",
" \"average_handle_time_seconds\": \"known\"\n",
" }\n",
" },\n",
" \"scores\": [\n",
" {\n",
" \"competency_id\": \"automation_ai_strategy\",\n",
" \"dimension\": \"strategy_value\",\n",
" \"score\": 2,\n",
" \"evidence\": \"AI driven by board pressure; no written thesis\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"value_realization\",\n",
" \"dimension\": \"strategy_value\",\n",
" \"score\": 2,\n",
" \"evidence\": \"Business cases pre-investment only\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"executive_alignment\",\n",
" \"dimension\": \"strategy_value\",\n",
" \"score\": 3,\n",
" \"evidence\": \"COO owns CX AI; steering meets quarterly\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"process_discovery\",\n",
" \"dimension\": \"foundations\",\n",
" \"score\": 3,\n",
" \"evidence\": \"Top 10 call reasons mapped with volumes\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"data_readiness\",\n",
" \"dimension\": \"foundations\",\n",
" \"score\": 2,\n",
" \"evidence\": \"KB stale; interaction data siloed in recordings\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"technical_architecture\",\n",
" \"dimension\": \"foundations\",\n",
" \"score\": 3,\n",
" \"evidence\": \"CCaaS APIs available; shared integration layer WIP\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"use_case_prioritization\",\n",
" \"dimension\": \"delivery\",\n",
" \"score\": 3,\n",
" \"evidence\": \"Scored backlog reviewed monthly\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"delivery_capability\",\n",
" \"dimension\": \"delivery\",\n",
" \"score\": 3,\n",
" \"evidence\": \"Two bots in production via SI partner\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"talent_and_skills\",\n",
" \"dimension\": \"delivery\",\n",
" \"score\": 2,\n",
" \"evidence\": \"One conversation designer, contractor\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"ai_operations\",\n",
" \"dimension\": \"sustain\",\n",
" \"score\": 2,\n",
" \"evidence\": \"Containment eyeballed weekly, no drift alerts\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"change_adoption\",\n",
" \"dimension\": \"sustain\",\n",
" \"score\": 3,\n",
" \"evidence\": \"Agent champions for copilot rollout\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" },\n",
" {\n",
" \"competency_id\": \"governance_and_risk\",\n",
" \"dimension\": \"sustain\",\n",
" \"score\": 3,\n",
" \"evidence\": \"AI policy signed; review board for voice bots\",\n",
" \"scorer_role\": \"facilitator\",\n",
" \"scored_at\": \"2026-07-19T19:45:38.063130\"\n",
" }\n",
" ],\n",
" \"computed_value\": {\n",
" \"theoretical_annual_value_low\": 2542500.0,\n",
" \"theoretical_annual_value_high\": 5085000.0,\n",
" \"realizable_18mo_low\": 953437.5,\n",
" \"realizable_18mo_high\": 3051000.0,\n",
" \"trapped_value_low\": 1525500.0,\n",
" \"trapped_value_high\": 3813750.0,\n",
" \"binding_constraints\": [\n",
" \"data_readiness\"\n",
" ],\n",
" \"unlock_sequence\": [\n",
" {\n",
" \"competency_ids\": [\n",
" \"data_readiness\"\n",
" ],\n",
" \"current_level\": 2,\n",
" \"target_level\": 3,\n",
" \"est_cost_low\": 300000.0,\n",
" \"est_cost_high\": 600000.0,\n",
" \"est_weeks\": 12,\n",
" \"value_unlocked_low\": 635625.0,\n",
" \"value_unlocked_high\": 1271250.0,\n",
" \"note\": \"\"\n",
" },\n",
" {\n",
" \"competency_ids\": [\n",
" \"process_discovery\",\n",
" \"data_readiness\",\n",
" \"technical_architecture\"\n",
" ],\n",
" \"current_level\": 3,\n",
" \"target_level\": 4,\n",
" \"est_cost_low\": 800000.0,\n",
" \"est_cost_high\": 1600000.0,\n",
" \"est_weeks\": 16,\n",
" \"value_unlocked_low\": 381375.00000000006,\n",
" \"value_unlocked_high\": 1016999.9999999998,\n",
" \"note\": \"joint lift — the tied competencies must move together to shift the cap\"\n",
" },\n",
" {\n",
" \"competency_ids\": [\n",
" \"process_discovery\",\n",
" \"data_readiness\",\n",
" \"technical_architecture\"\n",
" ],\n",
" \"current_level\": 4,\n",
" \"target_level\": 5,\n",
" \"est_cost_low\": 1050000.0,\n",
" \"est_cost_high\": 2100000.0,\n",
" \"est_weeks\": 20,\n",
" \"value_unlocked_low\": 381375.00000000006,\n",
" \"value_unlocked_high\": 762750.0000000001,\n",
" \"note\": \"joint lift — the tied competencies must move together to shift the cap\"\n",
" }\n",
" ],\n",
" \"weakest_foundational_score\": 2,\n",
" \"realization_factor_low\": 0.25,\n",
" \"realization_factor_high\": 0.4,\n",
" \"driver_values\": [\n",
" {\n",
" \"driver_id\": \"deflection_lift\",\n",
" \"name\": \"Deflection / containment improvement\",\n",
" \"theoretical_low\": 1170000.0,\n",
" \"theoretical_high\": 2730000.0\n",
" },\n",
" {\n",
" \"driver_id\": \"aht_reduction\",\n",
" \"name\": \"Average handle time reduction\",\n",
" \"theoretical_low\": 1170000.0,\n",
" \"theoretical_high\": 1950000.0\n",
" },\n",
" {\n",
" \"driver_id\": \"attrition_reduction\",\n",
" \"name\": \"Attrition reduction\",\n",
" \"theoretical_low\": 202500.0,\n",
" \"theoretical_high\": 405000.0\n",
" }\n",
" ],\n",
" \"warnings\": []\n",
" },\n",
" \"notes\": \"\"\n",
"}\n",
"```\n"
]
}
],
"source": [
"# ── Data appendix — LLM-readable dump of the engagement ─────────────\n",
"# Renders backstage only (JupyterLab / nbconvert exports).\n",
"backstage(\"#### Capability scores\\n\")\n",
"_rows = [\"| Competency | Dimension | Score | Evidence |\", \"|---|---|---:|---|\"]\n",
"for _s in SCORES:\n",
" _cc = CONFIG.competency(_s.competency_id)\n",
" _ev = _s.evidence.replace(\"|\", \"\\\\|\") or \"—\"\n",
" _rows.append(f\"| {_cc.name} | {DIMENSION_NAME[_s.dimension]} | \"\n",
" f\"{_s.score} | {_ev} |\")\n",
"backstage(\"\\n\".join(_rows))\n",
"\n",
"backstage(\"\\n#### Dimension rollup\\n\")\n",
"_rows = [\"| Dimension | Mean score |\", \"|---|---:|\"]\n",
"for _did, _dname, _mean in dimension_rollup(CONFIG, SCORES):\n",
" _rows.append(f\"| {_dname} | {_mean:.2f} |\")\n",
"backstage(\"\\n\".join(_rows))\n",
"\n",
"if CONFIG.value_drivers:\n",
" backstage(\"\\n#### Value drivers (theoretical annual)\\n\")\n",
" _rows = [\"| Driver | Low | High |\", \"|---|---:|---:|\"]\n",
" for _d in VAS.driver_values:\n",
" _rows.append(f\"| {_d.name} | {money(_d.theoretical_low)} | \"\n",
" f\"{money(_d.theoretical_high)} |\")\n",
" _rows.append(f\"| **Total** | **{money(VAS.theoretical_annual_value_low)}** \"\n",
" f\"| **{money(VAS.theoretical_annual_value_high)}** |\")\n",
" backstage(\"\\n\".join(_rows))\n",
" backstage(f\"\\nRealization band at weakest foundation level \"\n",
" f\"{VAS.weakest_foundational_score}: \"\n",
" f\"{VAS.realization_factor_low:.0%}-{VAS.realization_factor_high:.0%} · \"\n",
" f\"realizable 18-mo {money(VAS.realizable_18mo_low)}-\"\n",
" f\"{money(VAS.realizable_18mo_high)} · trapped \"\n",
" f\"{money(VAS.trapped_value_low)}-{money(VAS.trapped_value_high)} \"\n",
" f\"per year · binding: {', '.join(VAS.binding_constraints)}\")\n",
"\n",
"backstage(\"\\n#### Engagement state (JSON)\\n\")\n",
"backstage(\"```json\")\n",
"backstage(engagement_json(ENGAGEMENT))\n",
"backstage(\"```\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d3272e77",
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-19T23:45:39.799620Z",
"iopub.status.busy": "2026-07-19T23:45:39.799494Z",
"iopub.status.idle": "2026-07-19T23:45:39.806031Z",
"shell.execute_reply": "2026-07-19T23:45:39.801884Z"
}
},
"outputs": [],
"source": [
"# ── Review a saved engagement (backstage utility, optional) ─────────\n",
"# Point _REVIEW_JSON at an exports/*.json and run in JupyterLab to\n",
"# reload a past engagement for review; the live session is untouched.\n",
"_REVIEW_JSON = \"\"\n",
"if _REVIEW_JSON:\n",
" from diaglib import load_engagement\n",
" _prev = load_engagement(pathlib.Path(_REVIEW_JSON))\n",
" backstage(f\"loaded {_prev.engagement_id}: {_prev.client_name} · \"\n",
" f\"{len(_prev.scores)} scores · \" + (\n",
" \"binding: \" + \", \".join(_prev.computed_value.binding_constraints)\n",
" if _prev.computed_value else \"no computed value\"))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.13.7"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {
"0134ad746d16416390a46248fe5e1aa3": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"1 · Automation & AI Strategy",
"2 · Value Realization",
"3 · Executive Alignment",
"4 · Process Discovery",
"5 · Data Readiness",
"6 · Technical Architecture",
"7 · Use Case Prioritization",
"8 · Delivery Capability",
"9 · Talent & Skills",
"10 · AI Operations",
"11 · Change & Adoption",
"12 · Governance & Risk"
],
"disabled": false,
"hidden": false,
"label": "Now scoring",
"layout": "IPY_MODEL_ac26fdaac4174281bce0b305c73f706e",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "1 · Automation & AI Strategy"
}
},
"0384abc193994b69881674157eb6b28f": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_610bb2af251a408ab9e2be886b901705",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_f86046c7d0fb4a79bf086f572ae62e00",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><h4 style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-weight: 800; color: #0f172a; line-height: 1.25; margin: 1.15em 0 0.45em; font-size: 1.15em;\">2 · Operational baseline</h4></div>"
}
},
"038b606123d74acd96d5e5b4581b409b": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"0ad924ecfd3544a8b982c2cefa3c2711": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"0ff9441dcf9947f5a45714eaf9ae9d54": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"10af45726b014b8a9bc5ca00fe713542": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"114ea157213646ccba3e4a6ea52c2856": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_bd2aa3a869924783b6f555b34d8ea40e",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_8a1ab813e289451aa5f34526f8e0737e",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><p style=\"margin: 0 0 1em;\"><strong style=\"font-weight: 700;\">Foundations</strong></p></div>"
}
},
"12b153c6fe8d4f7db07a58270abc11d8": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — AI Operations",
"layout": "IPY_MODEL_6f5a203d97274d19904c0bb9033decb6",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 2
}
},
"1b52fe1f13244689890ce4228dd759bd": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"1dd77bf8ef284086a98c3f506dac122d": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Value Realization",
"layout": "IPY_MODEL_a28bd95a94df42179c0b2c182073295e",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Business cases pre-investment only"
}
},
"1e1189045b604913a5383ec4b05aff36": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"1e974ed77efd47a799a206ac2876d7f7": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"25453e259ab74dfc84ec36936f484d21": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"275ca35bfb974e3bab5d507f521fc4c2": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Change & Adoption",
"layout": "IPY_MODEL_e87bd4c43bc247b48eba80646bacc41b",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"2782d2713dfc449aaa69d11007cace4e": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.date.DateInputWidget",
"_css": "\n .mljar-date-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-date-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-date-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n box-sizing: border-box;\n line-height: 1.4;\n }\n\n .mljar-date-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-date-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n @media (max-width: 768px) {\n .mljar-date-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-date-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-date-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"date\";\n input.classList.add(\"mljar-date-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Date\";\n input.value = model.get(\"value\") || \"\";\n\n const min = model.get(\"min\") || \"\";\n const max = model.get(\"max\") || \"\";\n if (min) input.min = min; else input.removeAttribute(\"min\");\n if (max) input.max = max; else input.removeAttribute(\"max\");\n\n input.disabled = !!model.get(\"disabled\");\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n }\n\n input.addEventListener(\"change\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n model.save_changes();\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Workshop date",
"layout": "IPY_MODEL_fd25d64cd05848d7958943957f7bd4a8",
"layout_path": null,
"max": "",
"min": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "2026-07-19"
}
},
"27875b6048174bd1985274a42a0d3945": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"2a2adb61fc124e4a8a489f341024af9d": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"2ebb37baa8404d2cabcaa2069aa1c212": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"2ef89a29c65c4d978ec5ced9504dba73": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Session notes",
"layout": "IPY_MODEL_27875b6048174bd1985274a42a0d3945",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": ""
}
},
"333656890d3a4dce8a18171604757325": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_0ad924ecfd3544a8b982c2cefa3c2711",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_038b606123d74acd96d5e5b4581b409b",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><p style=\"margin: 0 0 1em;\"><strong style=\"font-weight: 700;\">Sustain</strong></p></div>"
}
},
"33c48116b82842f8b1a571804a90ebca": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — AI Operations",
"layout": "IPY_MODEL_93574dd500a84b89aa94f05b5ba94a80",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Containment eyeballed weekly, no drift alerts"
}
},
"36927983549046499f7d080a20c1b0b8": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Delivery Capability",
"layout": "IPY_MODEL_1e974ed77efd47a799a206ac2876d7f7",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"39ce7dffb71b41b7a2d6f14e63b2ad15": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Process Discovery",
"layout": "IPY_MODEL_d09a3c1bbcd24f1f86cb58a767a59a60",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"40697a7b3df442ffb315149b61aaa646": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Change & Adoption",
"layout": "IPY_MODEL_707cddf03ec34123a416f7b22e3b71b6",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Agent champions for copilot rollout"
}
},
"42c73613a5b44fdcb4113156c70012a0": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"45b419ade2d446f887aefbcc8167ba6a": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Use Case Prioritization",
"layout": "IPY_MODEL_d8226a602bb84ef8898dfb8b66007001",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"4b2a68f2a2a7491aa8a3fbee02365047": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"4bbea152c5354344bad9cae9ae4b131f": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_aa44af8d77fb41ad885aa091b4f6f537",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_915770f5a3354ee1812203cedd0266cb",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><h4 style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-weight: 800; color: #0f172a; line-height: 1.25; margin: 1.15em 0 0.45em; font-size: 1.15em;\">3 · Capability scoring</h4></div>"
}
},
"508f349cd9c9427e99d1a47c6cfcef51": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"58a702be2cb942929305bed89ee052cc": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"5c48b8be8ec14795ae22f3bc29e083fc": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"5cc39b1eef054bc9a484708bbcf282ee": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Data Readiness",
"layout": "IPY_MODEL_a9e69ba0e42443bfae92ade55d144b11",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 2
}
},
"5feaf4858ee043a8b09f3507ce84f49c": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_d99bfdd7c8144a5793f3c6fcc0153738",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_afb9325b4b9a49be9b56e02669e85d07",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><h4 style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-weight: 800; color: #0f172a; line-height: 1.25; margin: 1.15em 0 0.45em; font-size: 1.15em;\">1 · Engagement</h4></div>"
}
},
"60fabcff9f5e4a37942bb364eccddb85": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.number.NumberInputWidget",
"_css": "\n .mljar-number-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-number-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-number-field-row {\n display: flex;\n align-items: stretch;\n width: 100%;\n min-height: 40px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n overflow: hidden;\n }\n\n .mljar-number-input {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 100%;\n padding: 7px 10px;\n border: 0;\n border-radius: 0;\n background: #ffffff;\n box-sizing: border-box;\n background-color: #ffffff !important;\n color: #0f172a !important;\n font: inherit;\n line-height: 1.2;\n -moz-appearance: textfield;\n }\n\n .mljar-number-input::-webkit-outer-spin-button,\n .mljar-number-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n\n .mljar-number-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-number-input:focus {\n outline: none;\n }\n\n .mljar-number-field-row:focus-within {\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-number-field-row:focus-within .mljar-number-controls {\n border-left-color: #007bff;\n }\n\n .mljar-number-controls {\n display: flex;\n align-items: stretch;\n flex: 0 0 auto;\n border-left: 1px solid #cfd1d5;\n background: #f1f1f2;\n }\n\n .mljar-number-step-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n min-width: 38px;\n min-height: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #0f172a;\n font: inherit;\n font-size: 18px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-number-step-up {\n border-left: 1px solid #cfd1d5;\n }\n\n .mljar-number-step-btn:hover {\n background: #f3f3f4;\n }\n\n .mljar-number-step-btn:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:focus-visible {\n outline: none;\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:disabled {\n background: #f5f5f5;\n color: #aaa;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-number-field-row {\n min-height: 44px;\n }\n\n .mljar-number-input {\n min-height: 44px;\n padding: 8px 12px;\n }\n\n .mljar-number-step-btn {\n font-size: 19px;\n width: 44px;\n min-width: 44px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-number-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-number-label\");\n\n const fieldRow = document.createElement(\"div\");\n fieldRow.classList.add(\"mljar-number-field-row\");\n\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.classList.add(\"mljar-number-input\");\n\n const decrementBtn = document.createElement(\"button\");\n decrementBtn.type = \"button\";\n decrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-down\");\n decrementBtn.textContent = \"-\";\n decrementBtn.setAttribute(\"aria-label\", \"Decrease value\");\n\n const incrementBtn = document.createElement(\"button\");\n incrementBtn.type = \"button\";\n incrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-up\");\n incrementBtn.textContent = \"+\";\n incrementBtn.setAttribute(\"aria-label\", \"Increase value\");\n\n const controls = document.createElement(\"div\");\n controls.classList.add(\"mljar-number-controls\");\n\n controls.appendChild(decrementBtn);\n controls.appendChild(incrementBtn);\n fieldRow.appendChild(input);\n fieldRow.appendChild(controls);\n\n container.appendChild(topLabel);\n container.appendChild(fieldRow);\n el.appendChild(container);\n\n function clamp(val, min, max) {\n if (Number.isFinite(min) && val < min) return min;\n if (Number.isFinite(max) && val > max) return max;\n return val;\n }\n\n function normalizeStep(step) {\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n function snapToStep(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = Math.round((value - base) / safeStep);\n const snapped = base + steps * safeStep;\n const precision = Math.max(\n 0,\n (String(safeStep).split(\".\")[1] || \"\").length\n );\n\n return Number(snapped.toFixed(precision + 2));\n }\n\n function isOnStepGrid(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = (value - base) / safeStep;\n const nearest = Math.round(steps);\n const epsilon = Math.max(1e-9, safeStep * 1e-9);\n\n return Math.abs(steps - nearest) <= epsilon;\n }\n\n function getCurrentBounds() {\n return {\n min: Number(model.get(\"min\")),\n max: Number(model.get(\"max\")),\n };\n }\n\n function isTransientDraft(raw) {\n return raw === \"\" || raw === \"-\" || raw === \".\" || raw === \"-.\";\n }\n\n let isEditing = false;\n const INPUT_COMMIT_DEBOUNCE_MS = 400;\n\n function clearPendingDraftCommit() {\n if (debounceTimer) clearTimeout(debounceTimer);\n pendingDraftValue = null;\n }\n\n function parseDraftValue(rawValue) {\n const raw = String(rawValue).trim();\n if (isTransientDraft(raw)) {\n return { kind: \"transient\" };\n }\n\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { kind: \"invalid\" };\n }\n\n return { kind: \"number\", value };\n }\n\n function commitValue(nextValue, saveNow = true) {\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n const parsed = parseDraftValue(nextValue);\n if (parsed.kind !== \"number\") {\n syncFromModel();\n return;\n }\n\n let v = parsed.value;\n v = clamp(v, min, max);\n v = snapToStep(v, min, step);\n v = clamp(v, min, max);\n input.value = String(v);\n model.set(\"value\", v);\n\n if (saveNow) {\n model.save_changes();\n }\n }\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter number\";\n\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const step = Number(model.get(\"step\"));\n\n if (Number.isFinite(min)) input.min = String(min); else input.removeAttribute(\"min\");\n if (Number.isFinite(max)) input.max = String(max); else input.removeAttribute(\"max\");\n if (Number.isFinite(step)) input.step = String(step); else input.removeAttribute(\"step\");\n\n const v = Number(model.get(\"value\"));\n if (!isEditing) {\n input.value = Number.isFinite(v) ? String(v) : \"\";\n }\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n incrementBtn.disabled = disabled;\n decrementBtn.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n let debounceTimer = null;\n let pendingDraftValue = null;\n input.addEventListener(\"focus\", () => {\n isEditing = true;\n });\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n\n const parsed = parseDraftValue(input.value);\n if (parsed.kind !== \"number\") {\n clearPendingDraftCommit();\n return;\n }\n\n const v = parsed.value;\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n if (Number.isFinite(min) && v < min) {\n clearPendingDraftCommit();\n return;\n }\n if (Number.isFinite(max) && v > max) {\n clearPendingDraftCommit();\n return;\n }\n if (!isOnStepGrid(v, min, step)) {\n clearPendingDraftCommit();\n return;\n }\n\n pendingDraftValue = v;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n if (pendingDraftValue === null) return;\n model.set(\"value\", pendingDraftValue);\n model.save_changes();\n pendingDraftValue = null;\n }, INPUT_COMMIT_DEBOUNCE_MS);\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n clearPendingDraftCommit();\n commitValue(input.value, true);\n });\n\n input.addEventListener(\"keydown\", event => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n input.blur();\n }\n });\n\n incrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base + step, min, step));\n });\n\n decrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base - step, min, step));\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:step\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n // ---- read cell id (no DOM modifications) ----\n /*\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Average handle time (seconds)",
"layout": "IPY_MODEL_d0d3383dcf3d4af8b765a09d74644425",
"layout_path": null,
"max": 3600.0,
"min": 0.0,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"step": 10.0,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 420.0
}
},
"610bb2af251a408ab9e2be886b901705": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"629f019ab17c4adfb3a0518af63453e8": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"6e04107870054b609461f8468f8117bf": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"6f5a203d97274d19904c0bb9033decb6": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"707cddf03ec34123a416f7b22e3b71b6": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"71ff8c98d8bb4c7096c0ea8a1b693def": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"738b9403a2cb4d3498f2e174430c6d5b": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Executive Alignment",
"layout": "IPY_MODEL_10af45726b014b8a9bc5ca00fe713542",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"73ab01b6ab4843b68ab1930a1b112e7a": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"741f4d5aeaf34ea6bebbba0b72f23426": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Technical Architecture",
"layout": "IPY_MODEL_2a2adb61fc124e4a8a489f341024af9d",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"74ca96bfbd7a44c7a87eb3c1e0a895e0": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Governance & Risk",
"layout": "IPY_MODEL_cc1eb0191f3840e5a9af90a9b1dd7a49",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 3
}
},
"780c3efc5ec54ecc9ea40ce81f52cc28": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"🟢 known",
"🟡 estimated",
"🔴 unknown"
],
"disabled": false,
"hidden": false,
"label": "Average handle time (seconds) — confidence",
"layout": "IPY_MODEL_6e04107870054b609461f8468f8117bf",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "🟢 known"
}
},
"7aa2b22ed12d4c1a9ff00e2432464da8": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Talent & Skills",
"layout": "IPY_MODEL_c84dfde6c7794e49907e69ef4ba27e57",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 2
}
},
"82b3e6f7ce29429b94f0beb47b226b59": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Use Case Prioritization",
"layout": "IPY_MODEL_8e0f8f895e244b24a2d00d6bbe064f50",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Scored backlog reviewed monthly"
}
},
"878ac4372b24422d9e06d9c6a77ed9b2": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.number.NumberInputWidget",
"_css": "\n .mljar-number-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-number-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-number-field-row {\n display: flex;\n align-items: stretch;\n width: 100%;\n min-height: 40px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n overflow: hidden;\n }\n\n .mljar-number-input {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 100%;\n padding: 7px 10px;\n border: 0;\n border-radius: 0;\n background: #ffffff;\n box-sizing: border-box;\n background-color: #ffffff !important;\n color: #0f172a !important;\n font: inherit;\n line-height: 1.2;\n -moz-appearance: textfield;\n }\n\n .mljar-number-input::-webkit-outer-spin-button,\n .mljar-number-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n\n .mljar-number-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-number-input:focus {\n outline: none;\n }\n\n .mljar-number-field-row:focus-within {\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-number-field-row:focus-within .mljar-number-controls {\n border-left-color: #007bff;\n }\n\n .mljar-number-controls {\n display: flex;\n align-items: stretch;\n flex: 0 0 auto;\n border-left: 1px solid #cfd1d5;\n background: #f1f1f2;\n }\n\n .mljar-number-step-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n min-width: 38px;\n min-height: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #0f172a;\n font: inherit;\n font-size: 18px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-number-step-up {\n border-left: 1px solid #cfd1d5;\n }\n\n .mljar-number-step-btn:hover {\n background: #f3f3f4;\n }\n\n .mljar-number-step-btn:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:focus-visible {\n outline: none;\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:disabled {\n background: #f5f5f5;\n color: #aaa;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-number-field-row {\n min-height: 44px;\n }\n\n .mljar-number-input {\n min-height: 44px;\n padding: 8px 12px;\n }\n\n .mljar-number-step-btn {\n font-size: 19px;\n width: 44px;\n min-width: 44px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-number-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-number-label\");\n\n const fieldRow = document.createElement(\"div\");\n fieldRow.classList.add(\"mljar-number-field-row\");\n\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.classList.add(\"mljar-number-input\");\n\n const decrementBtn = document.createElement(\"button\");\n decrementBtn.type = \"button\";\n decrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-down\");\n decrementBtn.textContent = \"-\";\n decrementBtn.setAttribute(\"aria-label\", \"Decrease value\");\n\n const incrementBtn = document.createElement(\"button\");\n incrementBtn.type = \"button\";\n incrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-up\");\n incrementBtn.textContent = \"+\";\n incrementBtn.setAttribute(\"aria-label\", \"Increase value\");\n\n const controls = document.createElement(\"div\");\n controls.classList.add(\"mljar-number-controls\");\n\n controls.appendChild(decrementBtn);\n controls.appendChild(incrementBtn);\n fieldRow.appendChild(input);\n fieldRow.appendChild(controls);\n\n container.appendChild(topLabel);\n container.appendChild(fieldRow);\n el.appendChild(container);\n\n function clamp(val, min, max) {\n if (Number.isFinite(min) && val < min) return min;\n if (Number.isFinite(max) && val > max) return max;\n return val;\n }\n\n function normalizeStep(step) {\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n function snapToStep(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = Math.round((value - base) / safeStep);\n const snapped = base + steps * safeStep;\n const precision = Math.max(\n 0,\n (String(safeStep).split(\".\")[1] || \"\").length\n );\n\n return Number(snapped.toFixed(precision + 2));\n }\n\n function isOnStepGrid(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = (value - base) / safeStep;\n const nearest = Math.round(steps);\n const epsilon = Math.max(1e-9, safeStep * 1e-9);\n\n return Math.abs(steps - nearest) <= epsilon;\n }\n\n function getCurrentBounds() {\n return {\n min: Number(model.get(\"min\")),\n max: Number(model.get(\"max\")),\n };\n }\n\n function isTransientDraft(raw) {\n return raw === \"\" || raw === \"-\" || raw === \".\" || raw === \"-.\";\n }\n\n let isEditing = false;\n const INPUT_COMMIT_DEBOUNCE_MS = 400;\n\n function clearPendingDraftCommit() {\n if (debounceTimer) clearTimeout(debounceTimer);\n pendingDraftValue = null;\n }\n\n function parseDraftValue(rawValue) {\n const raw = String(rawValue).trim();\n if (isTransientDraft(raw)) {\n return { kind: \"transient\" };\n }\n\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { kind: \"invalid\" };\n }\n\n return { kind: \"number\", value };\n }\n\n function commitValue(nextValue, saveNow = true) {\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n const parsed = parseDraftValue(nextValue);\n if (parsed.kind !== \"number\") {\n syncFromModel();\n return;\n }\n\n let v = parsed.value;\n v = clamp(v, min, max);\n v = snapToStep(v, min, step);\n v = clamp(v, min, max);\n input.value = String(v);\n model.set(\"value\", v);\n\n if (saveNow) {\n model.save_changes();\n }\n }\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter number\";\n\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const step = Number(model.get(\"step\"));\n\n if (Number.isFinite(min)) input.min = String(min); else input.removeAttribute(\"min\");\n if (Number.isFinite(max)) input.max = String(max); else input.removeAttribute(\"max\");\n if (Number.isFinite(step)) input.step = String(step); else input.removeAttribute(\"step\");\n\n const v = Number(model.get(\"value\"));\n if (!isEditing) {\n input.value = Number.isFinite(v) ? String(v) : \"\";\n }\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n incrementBtn.disabled = disabled;\n decrementBtn.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n let debounceTimer = null;\n let pendingDraftValue = null;\n input.addEventListener(\"focus\", () => {\n isEditing = true;\n });\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n\n const parsed = parseDraftValue(input.value);\n if (parsed.kind !== \"number\") {\n clearPendingDraftCommit();\n return;\n }\n\n const v = parsed.value;\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n if (Number.isFinite(min) && v < min) {\n clearPendingDraftCommit();\n return;\n }\n if (Number.isFinite(max) && v > max) {\n clearPendingDraftCommit();\n return;\n }\n if (!isOnStepGrid(v, min, step)) {\n clearPendingDraftCommit();\n return;\n }\n\n pendingDraftValue = v;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n if (pendingDraftValue === null) return;\n model.set(\"value\", pendingDraftValue);\n model.save_changes();\n pendingDraftValue = null;\n }, INPUT_COMMIT_DEBOUNCE_MS);\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n clearPendingDraftCommit();\n commitValue(input.value, true);\n });\n\n input.addEventListener(\"keydown\", event => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n input.blur();\n }\n });\n\n incrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base + step, min, step));\n });\n\n decrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base - step, min, step));\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:step\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n // ---- read cell id (no DOM modifications) ----\n /*\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Blended cost per contact ($)",
"layout": "IPY_MODEL_58a702be2cb942929305bed89ee052cc",
"layout_path": null,
"max": 100.0,
"min": 0.0,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"step": 0.25,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 6.5
}
},
"8843aabb37b748a78228f4b18c49e6aa": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.number.NumberInputWidget",
"_css": "\n .mljar-number-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-number-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-number-field-row {\n display: flex;\n align-items: stretch;\n width: 100%;\n min-height: 40px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n overflow: hidden;\n }\n\n .mljar-number-input {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 100%;\n padding: 7px 10px;\n border: 0;\n border-radius: 0;\n background: #ffffff;\n box-sizing: border-box;\n background-color: #ffffff !important;\n color: #0f172a !important;\n font: inherit;\n line-height: 1.2;\n -moz-appearance: textfield;\n }\n\n .mljar-number-input::-webkit-outer-spin-button,\n .mljar-number-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n\n .mljar-number-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-number-input:focus {\n outline: none;\n }\n\n .mljar-number-field-row:focus-within {\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-number-field-row:focus-within .mljar-number-controls {\n border-left-color: #007bff;\n }\n\n .mljar-number-controls {\n display: flex;\n align-items: stretch;\n flex: 0 0 auto;\n border-left: 1px solid #cfd1d5;\n background: #f1f1f2;\n }\n\n .mljar-number-step-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n min-width: 38px;\n min-height: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #0f172a;\n font: inherit;\n font-size: 18px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-number-step-up {\n border-left: 1px solid #cfd1d5;\n }\n\n .mljar-number-step-btn:hover {\n background: #f3f3f4;\n }\n\n .mljar-number-step-btn:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:focus-visible {\n outline: none;\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:disabled {\n background: #f5f5f5;\n color: #aaa;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-number-field-row {\n min-height: 44px;\n }\n\n .mljar-number-input {\n min-height: 44px;\n padding: 8px 12px;\n }\n\n .mljar-number-step-btn {\n font-size: 19px;\n width: 44px;\n min-width: 44px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-number-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-number-label\");\n\n const fieldRow = document.createElement(\"div\");\n fieldRow.classList.add(\"mljar-number-field-row\");\n\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.classList.add(\"mljar-number-input\");\n\n const decrementBtn = document.createElement(\"button\");\n decrementBtn.type = \"button\";\n decrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-down\");\n decrementBtn.textContent = \"-\";\n decrementBtn.setAttribute(\"aria-label\", \"Decrease value\");\n\n const incrementBtn = document.createElement(\"button\");\n incrementBtn.type = \"button\";\n incrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-up\");\n incrementBtn.textContent = \"+\";\n incrementBtn.setAttribute(\"aria-label\", \"Increase value\");\n\n const controls = document.createElement(\"div\");\n controls.classList.add(\"mljar-number-controls\");\n\n controls.appendChild(decrementBtn);\n controls.appendChild(incrementBtn);\n fieldRow.appendChild(input);\n fieldRow.appendChild(controls);\n\n container.appendChild(topLabel);\n container.appendChild(fieldRow);\n el.appendChild(container);\n\n function clamp(val, min, max) {\n if (Number.isFinite(min) && val < min) return min;\n if (Number.isFinite(max) && val > max) return max;\n return val;\n }\n\n function normalizeStep(step) {\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n function snapToStep(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = Math.round((value - base) / safeStep);\n const snapped = base + steps * safeStep;\n const precision = Math.max(\n 0,\n (String(safeStep).split(\".\")[1] || \"\").length\n );\n\n return Number(snapped.toFixed(precision + 2));\n }\n\n function isOnStepGrid(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = (value - base) / safeStep;\n const nearest = Math.round(steps);\n const epsilon = Math.max(1e-9, safeStep * 1e-9);\n\n return Math.abs(steps - nearest) <= epsilon;\n }\n\n function getCurrentBounds() {\n return {\n min: Number(model.get(\"min\")),\n max: Number(model.get(\"max\")),\n };\n }\n\n function isTransientDraft(raw) {\n return raw === \"\" || raw === \"-\" || raw === \".\" || raw === \"-.\";\n }\n\n let isEditing = false;\n const INPUT_COMMIT_DEBOUNCE_MS = 400;\n\n function clearPendingDraftCommit() {\n if (debounceTimer) clearTimeout(debounceTimer);\n pendingDraftValue = null;\n }\n\n function parseDraftValue(rawValue) {\n const raw = String(rawValue).trim();\n if (isTransientDraft(raw)) {\n return { kind: \"transient\" };\n }\n\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { kind: \"invalid\" };\n }\n\n return { kind: \"number\", value };\n }\n\n function commitValue(nextValue, saveNow = true) {\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n const parsed = parseDraftValue(nextValue);\n if (parsed.kind !== \"number\") {\n syncFromModel();\n return;\n }\n\n let v = parsed.value;\n v = clamp(v, min, max);\n v = snapToStep(v, min, step);\n v = clamp(v, min, max);\n input.value = String(v);\n model.set(\"value\", v);\n\n if (saveNow) {\n model.save_changes();\n }\n }\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter number\";\n\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const step = Number(model.get(\"step\"));\n\n if (Number.isFinite(min)) input.min = String(min); else input.removeAttribute(\"min\");\n if (Number.isFinite(max)) input.max = String(max); else input.removeAttribute(\"max\");\n if (Number.isFinite(step)) input.step = String(step); else input.removeAttribute(\"step\");\n\n const v = Number(model.get(\"value\"));\n if (!isEditing) {\n input.value = Number.isFinite(v) ? String(v) : \"\";\n }\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n incrementBtn.disabled = disabled;\n decrementBtn.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n let debounceTimer = null;\n let pendingDraftValue = null;\n input.addEventListener(\"focus\", () => {\n isEditing = true;\n });\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n\n const parsed = parseDraftValue(input.value);\n if (parsed.kind !== \"number\") {\n clearPendingDraftCommit();\n return;\n }\n\n const v = parsed.value;\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n if (Number.isFinite(min) && v < min) {\n clearPendingDraftCommit();\n return;\n }\n if (Number.isFinite(max) && v > max) {\n clearPendingDraftCommit();\n return;\n }\n if (!isOnStepGrid(v, min, step)) {\n clearPendingDraftCommit();\n return;\n }\n\n pendingDraftValue = v;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n if (pendingDraftValue === null) return;\n model.set(\"value\", pendingDraftValue);\n model.save_changes();\n pendingDraftValue = null;\n }, INPUT_COMMIT_DEBOUNCE_MS);\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n clearPendingDraftCommit();\n commitValue(input.value, true);\n });\n\n input.addEventListener(\"keydown\", event => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n input.blur();\n }\n });\n\n incrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base + step, min, step));\n });\n\n decrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base - step, min, step));\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:step\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n // ---- read cell id (no DOM modifications) ----\n /*\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Annual attrition rate (0-1)",
"layout": "IPY_MODEL_f24ef21b03f04b90aaad8349a7f2ce48",
"layout_path": null,
"max": 1.0,
"min": 0.0,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"step": 0.01,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 0.3
}
},
"8a1ab813e289451aa5f34526f8e0737e": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"8bb4e603517a49d7a9976ee555dff224": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Talent & Skills",
"layout": "IPY_MODEL_ec91c552f127474f8796fdca5b55ddf6",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "One conversation designer, contractor"
}
},
"8e0f8f895e244b24a2d00d6bbe064f50": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"8eaaa94d855d4747afed128c16d66308": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Automation & AI Strategy",
"layout": "IPY_MODEL_ede38c77a96945ca91a33dbe0c80c221",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 2
}
},
"90d4dc2d15514ebda566e852ce78bf73": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.number.NumberInputWidget",
"_css": "\n .mljar-number-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-number-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-number-field-row {\n display: flex;\n align-items: stretch;\n width: 100%;\n min-height: 40px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n overflow: hidden;\n }\n\n .mljar-number-input {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 100%;\n padding: 7px 10px;\n border: 0;\n border-radius: 0;\n background: #ffffff;\n box-sizing: border-box;\n background-color: #ffffff !important;\n color: #0f172a !important;\n font: inherit;\n line-height: 1.2;\n -moz-appearance: textfield;\n }\n\n .mljar-number-input::-webkit-outer-spin-button,\n .mljar-number-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n\n .mljar-number-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-number-input:focus {\n outline: none;\n }\n\n .mljar-number-field-row:focus-within {\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-number-field-row:focus-within .mljar-number-controls {\n border-left-color: #007bff;\n }\n\n .mljar-number-controls {\n display: flex;\n align-items: stretch;\n flex: 0 0 auto;\n border-left: 1px solid #cfd1d5;\n background: #f1f1f2;\n }\n\n .mljar-number-step-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n min-width: 38px;\n min-height: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #0f172a;\n font: inherit;\n font-size: 18px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-number-step-up {\n border-left: 1px solid #cfd1d5;\n }\n\n .mljar-number-step-btn:hover {\n background: #f3f3f4;\n }\n\n .mljar-number-step-btn:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:focus-visible {\n outline: none;\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:disabled {\n background: #f5f5f5;\n color: #aaa;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-number-field-row {\n min-height: 44px;\n }\n\n .mljar-number-input {\n min-height: 44px;\n padding: 8px 12px;\n }\n\n .mljar-number-step-btn {\n font-size: 19px;\n width: 44px;\n min-width: 44px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-number-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-number-label\");\n\n const fieldRow = document.createElement(\"div\");\n fieldRow.classList.add(\"mljar-number-field-row\");\n\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.classList.add(\"mljar-number-input\");\n\n const decrementBtn = document.createElement(\"button\");\n decrementBtn.type = \"button\";\n decrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-down\");\n decrementBtn.textContent = \"-\";\n decrementBtn.setAttribute(\"aria-label\", \"Decrease value\");\n\n const incrementBtn = document.createElement(\"button\");\n incrementBtn.type = \"button\";\n incrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-up\");\n incrementBtn.textContent = \"+\";\n incrementBtn.setAttribute(\"aria-label\", \"Increase value\");\n\n const controls = document.createElement(\"div\");\n controls.classList.add(\"mljar-number-controls\");\n\n controls.appendChild(decrementBtn);\n controls.appendChild(incrementBtn);\n fieldRow.appendChild(input);\n fieldRow.appendChild(controls);\n\n container.appendChild(topLabel);\n container.appendChild(fieldRow);\n el.appendChild(container);\n\n function clamp(val, min, max) {\n if (Number.isFinite(min) && val < min) return min;\n if (Number.isFinite(max) && val > max) return max;\n return val;\n }\n\n function normalizeStep(step) {\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n function snapToStep(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = Math.round((value - base) / safeStep);\n const snapped = base + steps * safeStep;\n const precision = Math.max(\n 0,\n (String(safeStep).split(\".\")[1] || \"\").length\n );\n\n return Number(snapped.toFixed(precision + 2));\n }\n\n function isOnStepGrid(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = (value - base) / safeStep;\n const nearest = Math.round(steps);\n const epsilon = Math.max(1e-9, safeStep * 1e-9);\n\n return Math.abs(steps - nearest) <= epsilon;\n }\n\n function getCurrentBounds() {\n return {\n min: Number(model.get(\"min\")),\n max: Number(model.get(\"max\")),\n };\n }\n\n function isTransientDraft(raw) {\n return raw === \"\" || raw === \"-\" || raw === \".\" || raw === \"-.\";\n }\n\n let isEditing = false;\n const INPUT_COMMIT_DEBOUNCE_MS = 400;\n\n function clearPendingDraftCommit() {\n if (debounceTimer) clearTimeout(debounceTimer);\n pendingDraftValue = null;\n }\n\n function parseDraftValue(rawValue) {\n const raw = String(rawValue).trim();\n if (isTransientDraft(raw)) {\n return { kind: \"transient\" };\n }\n\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { kind: \"invalid\" };\n }\n\n return { kind: \"number\", value };\n }\n\n function commitValue(nextValue, saveNow = true) {\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n const parsed = parseDraftValue(nextValue);\n if (parsed.kind !== \"number\") {\n syncFromModel();\n return;\n }\n\n let v = parsed.value;\n v = clamp(v, min, max);\n v = snapToStep(v, min, step);\n v = clamp(v, min, max);\n input.value = String(v);\n model.set(\"value\", v);\n\n if (saveNow) {\n model.save_changes();\n }\n }\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter number\";\n\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const step = Number(model.get(\"step\"));\n\n if (Number.isFinite(min)) input.min = String(min); else input.removeAttribute(\"min\");\n if (Number.isFinite(max)) input.max = String(max); else input.removeAttribute(\"max\");\n if (Number.isFinite(step)) input.step = String(step); else input.removeAttribute(\"step\");\n\n const v = Number(model.get(\"value\"));\n if (!isEditing) {\n input.value = Number.isFinite(v) ? String(v) : \"\";\n }\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n incrementBtn.disabled = disabled;\n decrementBtn.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n let debounceTimer = null;\n let pendingDraftValue = null;\n input.addEventListener(\"focus\", () => {\n isEditing = true;\n });\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n\n const parsed = parseDraftValue(input.value);\n if (parsed.kind !== \"number\") {\n clearPendingDraftCommit();\n return;\n }\n\n const v = parsed.value;\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n if (Number.isFinite(min) && v < min) {\n clearPendingDraftCommit();\n return;\n }\n if (Number.isFinite(max) && v > max) {\n clearPendingDraftCommit();\n return;\n }\n if (!isOnStepGrid(v, min, step)) {\n clearPendingDraftCommit();\n return;\n }\n\n pendingDraftValue = v;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n if (pendingDraftValue === null) return;\n model.set(\"value\", pendingDraftValue);\n model.save_changes();\n pendingDraftValue = null;\n }, INPUT_COMMIT_DEBOUNCE_MS);\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n clearPendingDraftCommit();\n commitValue(input.value, true);\n });\n\n input.addEventListener(\"keydown\", event => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n input.blur();\n }\n });\n\n incrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base + step, min, step));\n });\n\n decrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base - step, min, step));\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:step\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n // ---- read cell id (no DOM modifications) ----\n /*\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Current containment rate (0-1)",
"layout": "IPY_MODEL_71ff8c98d8bb4c7096c0ea8a1b693def",
"layout_path": null,
"max": 1.0,
"min": 0.0,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"step": 0.01,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 0.2
}
},
"915770f5a3354ee1812203cedd0266cb": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"915ec41832064b9cb8b85fbcf17d028e": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"93574dd500a84b89aa94f05b5ba94a80": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"955923ab919f4bce897169977d539ea5": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Facilitator",
"layout": "IPY_MODEL_dc331c6bb2614915837a1db56ca9f7ae",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Robert Helewka"
}
},
"956c843fdb3847f6a6e9e8f07824acb9": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"🟢 known",
"🟡 estimated",
"🔴 unknown"
],
"disabled": false,
"hidden": false,
"label": "Blended cost per contact ($) — confidence",
"layout": "IPY_MODEL_915ec41832064b9cb8b85fbcf17d028e",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "🟡 estimated"
}
},
"96a1888c76f24e1ebc7f86c991ada96e": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Process Discovery",
"layout": "IPY_MODEL_0ff9441dcf9947f5a45714eaf9ae9d54",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Top 10 call reasons mapped with volumes"
}
},
"9c7d24f3d7b64b3e858baaa83002d48d": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"🟢 known",
"🟡 estimated",
"🔴 unknown"
],
"disabled": false,
"hidden": false,
"label": "Agent headcount — confidence",
"layout": "IPY_MODEL_a0b1e3e6878a47148a8c044aa98fb0dd",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "🟢 known"
}
},
"9ede9faa5bc44112a30d3093c7709cbc": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_defd950214494c0981a4965bbb354bea",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_1b52fe1f13244689890ce4228dd759bd",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><p style=\"margin: 0 0 1em;\"><strong style=\"font-weight: 700;\">Strategy &amp; Value</strong></p></div>"
}
},
"a002cefb6acf4098893088f19c7430d7": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"a0b1e3e6878a47148a8c044aa98fb0dd": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"a28bd95a94df42179c0b2c182073295e": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"a32316625a884fa5887079be7390601f": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.button.ButtonWidget",
"_css": "\n .mljar-button-container {\n display: inline-flex;\n width: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n padding-left: 4px;\n padding-right: 4px;\n }\n\n .mljar-button {\n border: 2px solid #007bff;\n background: #007bff;\n color: #ffffff;\n border-radius: 6px !important;\n padding: 6px 18px;\n margin-top: 5px;\n margin-bottom: 5px;\n cursor: pointer;\n transition: background 0.2s, color 0.2s, border-color 0.2s;\n user-select: none;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font-size: 1.08em;\n font-weight: 600;\n }\n\n .mljar-button:hover:not(:disabled) {\n background: #f3f3f4;\n color: #007bff;\n }\n\n .mljar-button:active:not(:disabled) {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-button:focus-visible {\n outline: none;\n border-color: #007bff;\n }\n\n .mljar-button:disabled {\n opacity: 0.8;\n cursor: not-allowed;\n }\n\n /* Variants */\n .mljar-button.is-primary {\n background: #007bff;\n color: #ffffff;\n border: 2px solid #007bff;\n }\n .mljar-button.is-primary:hover:not(:disabled) {\n background: #f3f3f4;\n color: #007bff;\n }\n\n .mljar-button.is-secondary {\n background: #ffffff;\n color: #0f172a;\n }\n\n .mljar-button.is-outline {\n background: transparent;\n color: #007bff;\n border: 2px solid #007bff;\n }\n .mljar-button.is-outline:hover:not(:disabled) {\n background: #f3f3f4;\n color: #007bff;\n }\n\n .mljar-button.is-danger {\n background: #dc3545;\n color: #fff;\n border-color: #dc3545;\n }\n .mljar-button.is-danger:hover:not(:disabled) {\n filter: brightness(0.98);\n background: #dc3545;\n color: #fff;\n }\n\n /* Sizes */\n .mljar-button.is-sm {\n padding: 4px 12px;\n font-size: 12px;\n border-radius: 4px;\n }\n .mljar-button.is-md {\n padding: 6px 18px;\n }\n .mljar-button.is-lg {\n padding: 8px 22px;\n font-size: 16px;\n border-radius: 10px;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-button-container\");\n\n const btn = document.createElement(\"button\");\n btn.classList.add(\"mljar-button\");\n\n function syncFromModel() {\n // label\n btn.textContent = model.get(\"label\") || \"Run\";\n\n // variant\n const v = model.get(\"variant\") || \"primary\";\n [\"is-primary\",\"is-secondary\",\"is-outline\",\"is-danger\"].forEach(c => btn.classList.remove(c));\n btn.classList.add(`is-${v}`);\n\n // size\n const s = model.get(\"size\") || \"md\";\n [\"is-sm\",\"is-md\",\"is-lg\"].forEach(c => btn.classList.remove(c));\n btn.classList.add(`is-${s}`);\n\n // disabled\n btn.disabled = !!model.get(\"disabled\");\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"inline-flex\";\n }\n\n btn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = model.get(\"n_clicks\") || 0;\n model.set(\"n_clicks\", current + 1);\n model.set(\"last_clicked_at\", new Date().toISOString());\n model.set(\"value\", true);\n model.save_changes();\n // model.send({ type: \"clicked\", n_clicks: current + 1 });\n });\n\n // Reactivity\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:variant\", syncFromModel);\n model.on(\"change:size\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n container.appendChild(btn);\n el.appendChild(container);\n\n syncFromModel();\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Export JSON + CSV",
"last_clicked_at": "",
"layout": "IPY_MODEL_e93aad95fc344e05a33c09ad369b21c3",
"layout_path": null,
"n_clicks": 0,
"position": "inline",
"render_slot_id": null,
"size": "md",
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"value": false,
"variant": "primary"
}
},
"a57e5835f51a4a0ea099d86287ba82bf": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_5c48b8be8ec14795ae22f3bc29e083fc",
"layout_path": null,
"placeholder": "",
"position": "inline",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_ef01e7fbeb1941ec8bfa0d387afe11fe",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><div style=\"max-width:860px\"><div style=\"margin:14px 0 8px\"><span title=\"Automation &amp; AI Strategy\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:2px solid #0072bc;border-radius:6px;background:#dcecfa;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">2</span><span title=\"Value Realization\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">2</span><span title=\"Executive Alignment\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span><span title=\"Process Discovery\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span><span title=\"Data Readiness\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">2</span><span title=\"Technical Architecture\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span><span title=\"Use Case Prioritization\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span><span title=\"Delivery Capability\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span><span title=\"Talent &amp; Skills\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">2</span><span title=\"AI Operations\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">2</span><span title=\"Change &amp; Adoption\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span><span title=\"Governance &amp; Risk\" style=\"display:inline-block;width:30px;height:30px;line-height:28px;text-align:center;border:1px solid #586671;border-radius:6px;background:#f8f8f8;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-right:5px\">3</span></div><div style=\"border:1px solid #d5d9db;border-radius:10px;background:#ffffff;padding:16px 20px\"><div style=\"font:600 12px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#0072bc;text-transform:uppercase;letter-spacing:.06em\">Strategy & Value</div><div style=\"font:700 21px Georgia, 'Times New Roman', serif;color:#151d2c;margin:2px 0 6px\">Automation &amp; AI Strategy</div><div style=\"font:15px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-bottom:6px\">Is there a written thesis for why AI, where, and what it changes about the operating model?</div><div style=\"font:italic 14px Georgia, 'Times New Roman', serif;color:#586671;margin-bottom:10px\">\"We&#x27;re doing AI because the CEO read an article.\"</div><table style=\"border-collapse:collapse;width:100%; width: 100%; border-collapse: collapse; margin: 0 0 1em;\"><tr><td style=\"padding:5px 12px;font:700 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;border-left:4px solid transparent;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">1</td><td style=\"padding:5px 8px;font:14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">No thesis. AI driven by executive impulse or vendor pitch.</td></tr><tr><td style=\"padding:5px 12px;font:700 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#0072bc;border-left:4px solid #0072bc;background:#dcecfa; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">2</td><td style=\"padding:5px 8px;font:600 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;background:#dcecfa; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Aspirational vision, no operating model implications defined.</td></tr><tr><td style=\"padding:5px 12px;font:700 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;border-left:4px solid transparent;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">3</td><td style=\"padding:5px 8px;font:14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Documented strategy, partial linkage to operating model.</td></tr><tr><td style=\"padding:5px 12px;font:700 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;border-left:4px solid transparent;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">4</td><td style=\"padding:5px 8px;font:14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Strategy drives portfolio decisions and operating model changes.</td></tr><tr><td style=\"padding:5px 12px;font:700 14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;border-left:4px solid transparent;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">5</td><td style=\"padding:5px 8px;font:14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;background:transparent; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Strategy is reviewed quarterly; operating model evolves with capability.</td></tr></table><div style=\"font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;margin-top:10px;border-top:1px solid #e2e6e9;padding-top:8px\"><b>Evidence:</b> <span style=\"color:#00a34c\">✓</span> AI driven by board pressure; no written thesis</div></div></div></div>"
}
},
"a6270c5418dc418c8bfcf49cfd662cc4": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"a7000c769e234457a69473437aea7491": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_ef0dadfa61ff4ba0a581baac678f060c",
"layout_path": null,
"placeholder": "",
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_629f019ab17c4adfb3a0518af63453e8",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><p style=\"margin: 0 0 1em;\"><strong style=\"font-weight: 700;\">Delivery</strong></p></div>"
}
},
"a76214e4ed5548de8e248286ea47d040": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLModel",
"state": {
"_dom_classes": [],
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/controls",
"_view_module_version": "2.0.0",
"_view_name": "HTMLView",
"cell_id": "",
"description": "",
"description_allow_html": false,
"layout": "IPY_MODEL_42c73613a5b44fdcb4113156c70012a0",
"layout_path": null,
"placeholder": "",
"position": "inline",
"render_slot_id": null,
"source_cell_id": null,
"style": "IPY_MODEL_f13438fbf2ef4d08948f8abc7386c998",
"tabbable": null,
"tooltip": null,
"value": "<div style=\"font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: normal; line-height: 1.65; color: #0f172a; word-break: break-word;\"><div style=\"max-width:860px\"><div style=\"font:700 24px Georgia, 'Times New Roman', serif;color:#151d2c;margin:4px 0 2px\">Acme Demo Co — CX AI Diagnostic</div><div style=\"font:14px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671;margin-bottom:8px\">Contact Center · 2026-07-19 · facilitated by Robert Helewka · evidence captured 12/12</div><div style=\"margin:6px 0 10px\"><span style=\"display:inline-block;border:1px solid #d5d9db;border-radius:14px;padding:2px 10px;margin:2px 6px 2px 0;font:12px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671\">Jane Example · VP Customer Experience <b style=\"color:#0072bc\">cx</b></span><span style=\"display:inline-block;border:1px solid #d5d9db;border-radius:14px;padding:2px 10px;margin:2px 6px 2px 0;font:12px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671\">Sam Sample · Contact Center Ops Director <b style=\"color:#0072bc\">ops</b></span></div><div style=\"border:1px solid #d5d9db;border-radius:10px;background:#f8f8f8;padding:10px 16px;display:inline-block\"><div style=\"font:700 13px Georgia, 'Times New Roman', serif;color:#151d2c;margin-bottom:4px\">Operational baseline</div><table style=\"border-collapse:collapse; width: 100%; border-collapse: collapse; margin: 0 0 1em;\"><tr><td style=\"padding:3px 14px 3px 0;font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Annual contact volume</td><td style=\"padding:3px 10px;font:600 13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;text-align:right; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">1,200,000</td><td style=\"padding:3px 0; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">🟢</td></tr><tr><td style=\"padding:3px 14px 3px 0;font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Blended cost per contact ($)</td><td style=\"padding:3px 10px;font:600 13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;text-align:right; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">6.50</td><td style=\"padding:3px 0; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">🟡</td></tr><tr><td style=\"padding:3px 14px 3px 0;font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Agent headcount</td><td style=\"padding:3px 10px;font:600 13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;text-align:right; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">450</td><td style=\"padding:3px 0; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">🟢</td></tr><tr><td style=\"padding:3px 14px 3px 0;font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Annual attrition rate (0-1)</td><td style=\"padding:3px 10px;font:600 13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;text-align:right; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">0.30</td><td style=\"padding:3px 0; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">🟡</td></tr><tr><td style=\"padding:3px 14px 3px 0;font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Current containment rate (0-1)</td><td style=\"padding:3px 10px;font:600 13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;text-align:right; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">0.20</td><td style=\"padding:3px 0; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">🟡</td></tr><tr><td style=\"padding:3px 14px 3px 0;font:13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#586671; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">Average handle time (seconds)</td><td style=\"padding:3px 10px;font:600 13px Arial, 'Helvetica Neue', Helvetica, sans-serif;color:#2e404d;text-align:right; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">420</td><td style=\"padding:3px 0; border: 1px solid #cfd1d5; padding: 0.55em 0.7em; text-align: left;\">🟢</td></tr></table></div></div></div>"
}
},
"a9e69ba0e42443bfae92ade55d144b11": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"aa44af8d77fb41ad885aa091b4f6f537": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"ac26fdaac4174281bce0b305c73f706e": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"afb9325b4b9a49be9b56e02669e85d07": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"b347ca14c69d40e8876ecb15b9f84241": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"b4527b9783fe43598a8d5846ac38e606": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"bae59fd8c40a4e16bde1f847d17c7192": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"contact_center",
"financial_services"
],
"disabled": false,
"hidden": false,
"label": "Industry config",
"layout": "IPY_MODEL_c6902106d5354710b75eac5ba59d5beb",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "contact_center"
}
},
"bd2aa3a869924783b6f555b34d8ea40e": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"bdf928b007aa4132aefb644a6b6c751b": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Executive Alignment",
"layout": "IPY_MODEL_f2ac82071dce4a89b8b98630090cd470",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "COO owns CX AI; steering meets quarterly"
}
},
"c0def29eb51e47f78e0c2bd3db3afc0a": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Data Readiness",
"layout": "IPY_MODEL_25453e259ab74dfc84ec36936f484d21",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "KB stale; interaction data siloed in recordings"
}
},
"c6902106d5354710b75eac5ba59d5beb": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"c82b1adbfcd44ff88abd892f4fd78301": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"🟢 known",
"🟡 estimated",
"🔴 unknown"
],
"disabled": false,
"hidden": false,
"label": "Current containment rate (0-1) — confidence",
"layout": "IPY_MODEL_b347ca14c69d40e8876ecb15b9f84241",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "🟡 estimated"
}
},
"c84dfde6c7794e49907e69ef4ba27e57": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"cc160d674e60481695cd07ca5098e1ca": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.number.NumberInputWidget",
"_css": "\n .mljar-number-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-number-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-number-field-row {\n display: flex;\n align-items: stretch;\n width: 100%;\n min-height: 40px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n overflow: hidden;\n }\n\n .mljar-number-input {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 100%;\n padding: 7px 10px;\n border: 0;\n border-radius: 0;\n background: #ffffff;\n box-sizing: border-box;\n background-color: #ffffff !important;\n color: #0f172a !important;\n font: inherit;\n line-height: 1.2;\n -moz-appearance: textfield;\n }\n\n .mljar-number-input::-webkit-outer-spin-button,\n .mljar-number-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n\n .mljar-number-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-number-input:focus {\n outline: none;\n }\n\n .mljar-number-field-row:focus-within {\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-number-field-row:focus-within .mljar-number-controls {\n border-left-color: #007bff;\n }\n\n .mljar-number-controls {\n display: flex;\n align-items: stretch;\n flex: 0 0 auto;\n border-left: 1px solid #cfd1d5;\n background: #f1f1f2;\n }\n\n .mljar-number-step-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n min-width: 38px;\n min-height: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #0f172a;\n font: inherit;\n font-size: 18px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-number-step-up {\n border-left: 1px solid #cfd1d5;\n }\n\n .mljar-number-step-btn:hover {\n background: #f3f3f4;\n }\n\n .mljar-number-step-btn:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:focus-visible {\n outline: none;\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:disabled {\n background: #f5f5f5;\n color: #aaa;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-number-field-row {\n min-height: 44px;\n }\n\n .mljar-number-input {\n min-height: 44px;\n padding: 8px 12px;\n }\n\n .mljar-number-step-btn {\n font-size: 19px;\n width: 44px;\n min-width: 44px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-number-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-number-label\");\n\n const fieldRow = document.createElement(\"div\");\n fieldRow.classList.add(\"mljar-number-field-row\");\n\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.classList.add(\"mljar-number-input\");\n\n const decrementBtn = document.createElement(\"button\");\n decrementBtn.type = \"button\";\n decrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-down\");\n decrementBtn.textContent = \"-\";\n decrementBtn.setAttribute(\"aria-label\", \"Decrease value\");\n\n const incrementBtn = document.createElement(\"button\");\n incrementBtn.type = \"button\";\n incrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-up\");\n incrementBtn.textContent = \"+\";\n incrementBtn.setAttribute(\"aria-label\", \"Increase value\");\n\n const controls = document.createElement(\"div\");\n controls.classList.add(\"mljar-number-controls\");\n\n controls.appendChild(decrementBtn);\n controls.appendChild(incrementBtn);\n fieldRow.appendChild(input);\n fieldRow.appendChild(controls);\n\n container.appendChild(topLabel);\n container.appendChild(fieldRow);\n el.appendChild(container);\n\n function clamp(val, min, max) {\n if (Number.isFinite(min) && val < min) return min;\n if (Number.isFinite(max) && val > max) return max;\n return val;\n }\n\n function normalizeStep(step) {\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n function snapToStep(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = Math.round((value - base) / safeStep);\n const snapped = base + steps * safeStep;\n const precision = Math.max(\n 0,\n (String(safeStep).split(\".\")[1] || \"\").length\n );\n\n return Number(snapped.toFixed(precision + 2));\n }\n\n function isOnStepGrid(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = (value - base) / safeStep;\n const nearest = Math.round(steps);\n const epsilon = Math.max(1e-9, safeStep * 1e-9);\n\n return Math.abs(steps - nearest) <= epsilon;\n }\n\n function getCurrentBounds() {\n return {\n min: Number(model.get(\"min\")),\n max: Number(model.get(\"max\")),\n };\n }\n\n function isTransientDraft(raw) {\n return raw === \"\" || raw === \"-\" || raw === \".\" || raw === \"-.\";\n }\n\n let isEditing = false;\n const INPUT_COMMIT_DEBOUNCE_MS = 400;\n\n function clearPendingDraftCommit() {\n if (debounceTimer) clearTimeout(debounceTimer);\n pendingDraftValue = null;\n }\n\n function parseDraftValue(rawValue) {\n const raw = String(rawValue).trim();\n if (isTransientDraft(raw)) {\n return { kind: \"transient\" };\n }\n\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { kind: \"invalid\" };\n }\n\n return { kind: \"number\", value };\n }\n\n function commitValue(nextValue, saveNow = true) {\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n const parsed = parseDraftValue(nextValue);\n if (parsed.kind !== \"number\") {\n syncFromModel();\n return;\n }\n\n let v = parsed.value;\n v = clamp(v, min, max);\n v = snapToStep(v, min, step);\n v = clamp(v, min, max);\n input.value = String(v);\n model.set(\"value\", v);\n\n if (saveNow) {\n model.save_changes();\n }\n }\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter number\";\n\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const step = Number(model.get(\"step\"));\n\n if (Number.isFinite(min)) input.min = String(min); else input.removeAttribute(\"min\");\n if (Number.isFinite(max)) input.max = String(max); else input.removeAttribute(\"max\");\n if (Number.isFinite(step)) input.step = String(step); else input.removeAttribute(\"step\");\n\n const v = Number(model.get(\"value\"));\n if (!isEditing) {\n input.value = Number.isFinite(v) ? String(v) : \"\";\n }\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n incrementBtn.disabled = disabled;\n decrementBtn.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n let debounceTimer = null;\n let pendingDraftValue = null;\n input.addEventListener(\"focus\", () => {\n isEditing = true;\n });\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n\n const parsed = parseDraftValue(input.value);\n if (parsed.kind !== \"number\") {\n clearPendingDraftCommit();\n return;\n }\n\n const v = parsed.value;\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n if (Number.isFinite(min) && v < min) {\n clearPendingDraftCommit();\n return;\n }\n if (Number.isFinite(max) && v > max) {\n clearPendingDraftCommit();\n return;\n }\n if (!isOnStepGrid(v, min, step)) {\n clearPendingDraftCommit();\n return;\n }\n\n pendingDraftValue = v;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n if (pendingDraftValue === null) return;\n model.set(\"value\", pendingDraftValue);\n model.save_changes();\n pendingDraftValue = null;\n }, INPUT_COMMIT_DEBOUNCE_MS);\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n clearPendingDraftCommit();\n commitValue(input.value, true);\n });\n\n input.addEventListener(\"keydown\", event => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n input.blur();\n }\n });\n\n incrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base + step, min, step));\n });\n\n decrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base - step, min, step));\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:step\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n // ---- read cell id (no DOM modifications) ----\n /*\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Annual contact volume",
"layout": "IPY_MODEL_4b2a68f2a2a7491aa8a3fbee02365047",
"layout_path": null,
"max": 100000000.0,
"min": 0.0,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"step": 10000.0,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 1200000.0
}
},
"cc1eb0191f3840e5a9af90a9b1dd7a49": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"d06eb8adf9994ae89d82f3983fdcf24f": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"d09a3c1bbcd24f1f86cb58a767a59a60": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"d0d3383dcf3d4af8b765a09d74644425": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"d34dbe00c35d4eb6b8a7da2340dbe2e1": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Participants — Name | Role | Function; ...",
"layout": "IPY_MODEL_a002cefb6acf4098893088f19c7430d7",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Jane Example | VP Customer Experience | cx; Sam Sample | Contact Center Ops Director | ops"
}
},
"d48a2c7bbda8440aa87e9078553f38e9": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.slider.SliderWidget",
"_css": "\n .mljar-slider-container {\n --mljar-slider-thumb-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0;\n width: 100%;\n max-width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .mljar-slider-stage {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding-top: 20px;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-floating-value {\n position: absolute;\n top: 0;\n left: 8px;\n transform: translateX(-50%);\n color: #007bff;\n font-weight: 700;\n font-size: 0.95em;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n }\n\n .mljar-slider-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .mljar-slider-row {\n position: relative;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: visible;\n box-sizing: border-box;\n }\n\n .mljar-slider-minmax-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n margin-top: 6px;\n color: #616673;\n font-size: 0.9em;\n line-height: 1.2;\n box-sizing: border-box;\n }\n\n .mljar-slider-min-label,\n .mljar-slider-max-label {\n color: inherit;\n white-space: nowrap;\n }\n\n .mljar-slider-input {\n display: block;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n border: none;\n height: 24px;\n padding: 0;\n margin: 0;\n cursor: pointer;\n box-sizing: border-box;\n }\n\n .mljar-slider-input:focus {\n outline: none;\n }\n\n .mljar-slider-input:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n .mljar-slider-input:focus-visible::-moz-range-thumb {\n box-shadow: 0 0 0 3px #e6f2ff;\n }\n\n /* Track */\n .mljar-slider-input::-webkit-slider-runnable-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n margin: auto;\n }\n .mljar-slider-input::-moz-range-track {\n height: 6px;\n background: #e0e0e0;\n border-radius: 6px;\n }\n\n /* Thumb */\n .mljar-slider-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n margin-top: -5px;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n .mljar-slider-input::-moz-range-thumb {\n width: var(--mljar-slider-thumb-size);\n height: var(--mljar-slider-thumb-size);\n border-radius: 50%;\n background: #007bff;\n cursor: pointer;\n transition: transform 0.14s ease, background-color 0.14s ease;\n }\n\n .mljar-slider-input:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n .mljar-slider-input:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:disabled::-moz-range-thumb {\n cursor: not-allowed;\n transform: none;\n }\n\n .mljar-slider-input:active::-webkit-slider-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n .mljar-slider-input:active::-moz-range-thumb {\n transform: scale(1.08);\n background: #007bff;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-slider-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-slider-top-label\");\n\n const sliderStage = document.createElement(\"div\");\n sliderStage.classList.add(\"mljar-slider-stage\");\n\n const floatingValueLabel = document.createElement(\"div\");\n floatingValueLabel.classList.add(\"mljar-slider-floating-value\");\n\n const sliderRow = document.createElement(\"div\");\n sliderRow.classList.add(\"mljar-slider-row\");\n\n const slider = document.createElement(\"input\");\n slider.type = \"range\";\n slider.classList.add(\"mljar-slider-input\");\n\n const minMaxRow = document.createElement(\"div\");\n minMaxRow.classList.add(\"mljar-slider-minmax-row\");\n\n const minLabel = document.createElement(\"span\");\n minLabel.classList.add(\"mljar-slider-min-label\");\n\n const maxLabel = document.createElement(\"span\");\n maxLabel.classList.add(\"mljar-slider-max-label\");\n\n function positionFloatingValue() {\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const value = Number(model.get(\"value\"));\n const range = max - min;\n const ratio = range <= 0 ? 0 : (value - min) / range;\n const clampedRatio = Math.max(0, Math.min(1, ratio));\n const computed = getComputedStyle(container);\n const thumbSize =\n parseFloat(computed.getPropertyValue(\"--mljar-slider-thumb-size\")) || 16;\n const inputWidth = slider.clientWidth || 0;\n const stageWidth = sliderStage.clientWidth || inputWidth || 0;\n const labelWidth = floatingValueLabel.offsetWidth || 0;\n\n if (inputWidth <= 0 || stageWidth <= 0) {\n return;\n }\n\n const sliderOffsetLeft = slider.offsetLeft || 0;\n const usableWidth = Math.max(0, inputWidth - thumbSize);\n const idealCenter =\n sliderOffsetLeft + thumbSize / 2 + clampedRatio * usableWidth;\n const halfLabel = labelWidth / 2;\n const minCenter = halfLabel;\n const maxCenter = Math.max(halfLabel, stageWidth - halfLabel);\n const finalCenter = Math.min(Math.max(idealCenter, minCenter), maxCenter);\n\n floatingValueLabel.style.left = `${finalCenter}px`;\n }\n\n function syncFromModel() {\n slider.min = model.get(\"min\");\n slider.max = model.get(\"max\");\n slider.value = model.get(\"value\");\n floatingValueLabel.textContent = String(model.get(\"value\"));\n minLabel.textContent = String(model.get(\"min\"));\n maxLabel.textContent = String(model.get(\"max\"));\n\n slider.disabled = !!model.get(\"disabled\");\n topLabel.textContent = model.get(\"label\") || \"Select number\";\n\n // hidden (exists but not visible)\n container.style.display = model.get(\"hidden\") ? \"none\" : \"flex\";\n positionFloatingValue();\n }\n\n let debounceTimer = null;\n slider.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", Number(slider.value));\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n model.save_changes();\n }, 100);\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n sliderRow.appendChild(slider);\n minMaxRow.appendChild(minLabel);\n minMaxRow.appendChild(maxLabel);\n\n container.appendChild(topLabel);\n sliderStage.appendChild(floatingValueLabel);\n sliderStage.appendChild(sliderRow);\n sliderStage.appendChild(minMaxRow);\n container.appendChild(sliderStage);\n el.appendChild(container);\n\n syncFromModel();\n\n const resizeObserver = new ResizeObserver(() => {\n positionFloatingValue();\n });\n resizeObserver.observe(sliderStage);\n\n return () => {\n resizeObserver.disconnect();\n };\n\n // ---- read cell id (no DOM modifications) ----\n /*const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Score — Value Realization",
"layout": "IPY_MODEL_e534d8601c624342ba4cf97686d0d9f4",
"layout_path": null,
"max": 5,
"min": 1,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 2
}
},
"d59db85587a8467dae0addb485bc3cbc": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"🟢 known",
"🟡 estimated",
"🔴 unknown"
],
"disabled": false,
"hidden": false,
"label": "Annual contact volume — confidence",
"layout": "IPY_MODEL_508f349cd9c9427e99d1a47c6cfcef51",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "🟢 known"
}
},
"d7940b33fc6f484582428064dfc25d0d": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Governance & Risk",
"layout": "IPY_MODEL_a6270c5418dc418c8bfcf49cfd662cc4",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "AI policy signed; review board for voice bots"
}
},
"d8226a602bb84ef8898dfb8b66007001": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"d885ae9c19e744248b31df0a37c3e498": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"d99bfdd7c8144a5793f3c6fcc0153738": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"dc331c6bb2614915837a1db56ca9f7ae": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"defd950214494c0981a4965bbb354bea": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"e534d8601c624342ba4cf97686d0d9f4": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"e87bd4c43bc247b48eba80646bacc41b": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"e91abb56e78a484598c5d47806b26282": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Delivery Capability",
"layout": "IPY_MODEL_2ebb37baa8404d2cabcaa2069aa1c212",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Two bots in production via SI partner"
}
},
"e93aad95fc344e05a33c09ad369b21c3": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"ec1d09aab4cd43d7821005f37d7acd59": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.select.SelectWidget",
"_css": "\n .mljar-select-container {\n position: relative;\n display: flex;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n overflow: visible;\n }\n\n .mljar-select-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-select-control {\n position: relative;\n display: flex;\n align-items: center;\n cursor: default;\n overflow: visible;\n }\n\n .mljar-select-container.is-open {\n z-index: 20;\n }\n\n .mljar-select-widget-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 36px 9px 10px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n line-height: 1.4;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n appearance: none !important;\n background-color: #ffffff !important;\n color: #0f172a !important;\n cursor: default;\n }\n\n .mljar-select-widget-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n cursor: text;\n }\n\n .mljar-select-caret {\n position: absolute;\n right: 12px;\n top: 50%;\n width: 8px;\n height: 8px;\n border-right: 1.5px solid #0f172a;\n border-bottom: 1.5px solid #0f172a;\n transform: translateY(-65%) rotate(45deg);\n pointer-events: auto;\n opacity: 0.5;\n transition: transform 0.18s ease, opacity 0.18s ease;\n }\n\n .mljar-select-container.is-open .mljar-select-caret {\n opacity: 1;\n transform: translateY(-35%) rotate(225deg);\n }\n\n .mljar-select-dropdown {\n display: none;\n position: fixed;\n z-index: 10000;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n }\n\n .mljar-select-list {\n max-height: 260px;\n overflow-y: auto;\n }\n\n .mljar-select-option {\n display: block;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n background: transparent;\n color: #0f172a;\n text-align: left;\n cursor: pointer;\n font: inherit;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-select-option:hover {\n background: #f3f3f4;\n }\n\n .mljar-select-option:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-option.is-selected {\n background: #e6f2ff;\n color: #007bff;\n font-weight: 600;\n }\n\n .mljar-select-option.is-selected:hover,\n .mljar-select-option.is-selected:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-select-empty {\n display: none;\n padding: 10px;\n color: #616673;\n font-size: 0.95em;\n }\n\n .mljar-select-widget-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-select-control.is-disabled .mljar-select-caret {\n opacity: 0.45;\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const normalize = value => String(value ?? \"\").toLowerCase().trim();\n const getChoices = () =>\n Array.isArray(model.get(\"choices\")) ? [...model.get(\"choices\")] : [];\n const isDisabled = () => !!model.get(\"disabled\");\n const isHidden = () => !!model.get(\"hidden\");\n\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-select-container\");\n\n if (model.get(\"label\")) {\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-select-label\");\n topLabel.innerHTML = model.get(\"label\");\n container.appendChild(topLabel);\n }\n\n const control = document.createElement(\"div\");\n control.classList.add(\"mljar-select-control\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-select-widget-input\");\n input.autocomplete = \"off\";\n input.spellcheck = false;\n\n const caret = document.createElement(\"div\");\n caret.classList.add(\"mljar-select-caret\");\n\n control.appendChild(input);\n control.appendChild(caret);\n\n const dropdown = document.createElement(\"div\");\n dropdown.classList.add(\"mljar-select-dropdown\");\n\n const list = document.createElement(\"div\");\n list.classList.add(\"mljar-select-list\");\n\n const emptyState = document.createElement(\"div\");\n emptyState.classList.add(\"mljar-select-empty\");\n emptyState.textContent = \"No matches\";\n\n dropdown.appendChild(list);\n dropdown.appendChild(emptyState);\n\n container.appendChild(control);\n el.appendChild(container);\n\n let isOpen = false;\n let filteredChoices = [];\n let lastCommittedValue = \"\";\n let isEditing = false;\n document.body.appendChild(dropdown);\n\n const updateDropdownPosition = () => {\n if (!isOpen) {\n return;\n }\n const rect = control.getBoundingClientRect();\n dropdown.style.top = `${rect.bottom + 6}px`;\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.width = `${rect.width}px`;\n };\n\n const setOpen = next => {\n if (isDisabled()) {\n isOpen = false;\n } else {\n isOpen = !!next;\n }\n container.classList.toggle(\"is-open\", isOpen);\n dropdown.style.display = isOpen ? \"block\" : \"none\";\n if (isOpen) {\n updateDropdownPosition();\n }\n };\n\n const updateDisabledState = () => {\n const disabled = isDisabled();\n input.disabled = disabled;\n control.classList.toggle(\"is-disabled\", disabled);\n };\n\n const updateHiddenState = () => {\n container.style.display = isHidden() ? \"none\" : \"\";\n };\n\n const syncInputWithValue = () => {\n const value = model.get(\"value\") || \"\";\n lastCommittedValue = value;\n if (!isEditing) {\n input.value = value;\n }\n };\n\n const filterChoices = query => {\n const normalizedQuery = normalize(query);\n const allChoices = getChoices();\n if (!normalizedQuery) {\n return allChoices;\n }\n return allChoices.filter(choice =>\n normalize(choice).includes(normalizedQuery)\n );\n };\n\n const renderList = () => {\n list.innerHTML = \"\";\n filteredChoices.forEach(choice => {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.classList.add(\"mljar-select-option\");\n if (choice === model.get(\"value\")) {\n option.classList.add(\"is-selected\");\n }\n option.textContent = choice;\n option.addEventListener(\"mousedown\", event => {\n event.preventDefault();\n event.stopPropagation();\n model.set(\"value\", choice);\n model.save_changes();\n isEditing = false;\n syncInputWithValue();\n renderList();\n setOpen(false);\n });\n list.appendChild(option);\n });\n\n const hasMatches = filteredChoices.length > 0;\n list.style.display = hasMatches ? \"block\" : \"none\";\n emptyState.style.display = hasMatches ? \"none\" : \"block\";\n };\n\n const refreshList = () => {\n filteredChoices = filterChoices(input.value);\n renderList();\n };\n\n const openWithCurrentQuery = () => {\n isEditing = true;\n input.value = \"\";\n refreshList();\n setOpen(true);\n };\n\n const closeDropdown = () => {\n isEditing = false;\n setOpen(false);\n input.value = lastCommittedValue;\n };\n\n control.addEventListener(\"click\", event => {\n event.stopPropagation();\n if (isDisabled()) {\n return;\n }\n if (event.target === caret && isOpen) {\n closeDropdown();\n input.blur();\n return;\n }\n openWithCurrentQuery();\n input.focus();\n });\n\n input.addEventListener(\"input\", () => {\n if (isDisabled()) {\n return;\n }\n refreshList();\n setOpen(true);\n });\n\n input.addEventListener(\"focus\", () => {\n if (isDisabled()) {\n return;\n }\n openWithCurrentQuery();\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n input.value = lastCommittedValue;\n });\n\n const handleDocumentClick = event => {\n if (!container.contains(event.target) && !dropdown.contains(event.target)) {\n closeDropdown();\n }\n };\n\n document.addEventListener(\"click\", handleDocumentClick);\n window.addEventListener(\"resize\", updateDropdownPosition);\n document.addEventListener(\"scroll\", updateDropdownPosition, true);\n\n model.on(\"change:value\", () => {\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:choices\", () => {\n const choices = getChoices();\n if (!choices.includes(model.get(\"value\")) && choices.length > 0) {\n model.set(\"value\", choices[0]);\n model.save_changes();\n return;\n }\n syncInputWithValue();\n refreshList();\n });\n\n model.on(\"change:disabled\", () => {\n updateDisabledState();\n if (isDisabled()) {\n closeDropdown();\n }\n });\n\n model.on(\"change:hidden\", () => {\n updateHiddenState();\n });\n\n updateDisabledState();\n updateHiddenState();\n syncInputWithValue();\n refreshList();\n setOpen(false);\n\n return () => {\n dropdown.remove();\n document.removeEventListener(\"click\", handleDocumentClick);\n window.removeEventListener(\"resize\", updateDropdownPosition);\n document.removeEventListener(\"scroll\", updateDropdownPosition, true);\n };\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"choices": [
"🟢 known",
"🟡 estimated",
"🔴 unknown"
],
"disabled": false,
"hidden": false,
"label": "Annual attrition rate (0-1) — confidence",
"layout": "IPY_MODEL_73ab01b6ab4843b68ab1930a1b112e7a",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "🟡 estimated"
}
},
"ec91c552f127474f8796fdca5b55ddf6": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"ede38c77a96945ca91a33dbe0c80c221": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"eecaf52a0a074f02a04efd099b4f22d9": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Automation & AI Strategy",
"layout": "IPY_MODEL_d06eb8adf9994ae89d82f3983fdcf24f",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "AI driven by board pressure; no written thesis"
}
},
"ef01e7fbeb1941ec8bfa0d387afe11fe": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"ef0dadfa61ff4ba0a581baac678f060c": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"f0ead6ff95fd46d598e4b8cd15cce31d": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Evidence — Technical Architecture",
"layout": "IPY_MODEL_d885ae9c19e744248b31df0a37c3e498",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "CCaaS APIs available; shared integration layer WIP"
}
},
"f13438fbf2ef4d08948f8abc7386c998": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"f24ef21b03f04b90aaad8349a7f2ce48": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"f2ac82071dce4a89b8b98630090cd470": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"f86046c7d0fb4a79bf086f572ae62e00": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "HTMLStyleModel",
"state": {
"_model_module": "@jupyter-widgets/controls",
"_model_module_version": "2.0.0",
"_model_name": "HTMLStyleModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "StyleView",
"background": null,
"description_width": "",
"font_size": null,
"text_color": null
}
},
"facdfdd6c0494307b51225d81b78aad8": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.number.NumberInputWidget",
"_css": "\n .mljar-number-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-number-label {\n padding-top: 6px;\n margin-bottom: 4px;\n font-weight: 600;\n }\n\n .mljar-number-field-row {\n display: flex;\n align-items: stretch;\n width: 100%;\n min-height: 40px;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n box-sizing: border-box;\n overflow: hidden;\n }\n\n .mljar-number-input {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 100%;\n padding: 7px 10px;\n border: 0;\n border-radius: 0;\n background: #ffffff;\n box-sizing: border-box;\n background-color: #ffffff !important;\n color: #0f172a !important;\n font: inherit;\n line-height: 1.2;\n -moz-appearance: textfield;\n }\n\n .mljar-number-input::-webkit-outer-spin-button,\n .mljar-number-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n\n .mljar-number-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n .mljar-number-input:focus {\n outline: none;\n }\n\n .mljar-number-field-row:focus-within {\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-number-field-row:focus-within .mljar-number-controls {\n border-left-color: #007bff;\n }\n\n .mljar-number-controls {\n display: flex;\n align-items: stretch;\n flex: 0 0 auto;\n border-left: 1px solid #cfd1d5;\n background: #f1f1f2;\n }\n\n .mljar-number-step-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n min-width: 38px;\n min-height: 100%;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #0f172a;\n font: inherit;\n font-size: 18px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n transition: background-color 0.14s ease, color 0.14s ease;\n }\n\n .mljar-number-step-up {\n border-left: 1px solid #cfd1d5;\n }\n\n .mljar-number-step-btn:hover {\n background: #f3f3f4;\n }\n\n .mljar-number-step-btn:active {\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:focus-visible {\n outline: none;\n background: #e6f2ff;\n color: #007bff;\n }\n\n .mljar-number-step-btn:disabled {\n background: #f5f5f5;\n color: #aaa;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-number-field-row {\n min-height: 44px;\n }\n\n .mljar-number-input {\n min-height: 44px;\n padding: 8px 12px;\n }\n\n .mljar-number-step-btn {\n font-size: 19px;\n width: 44px;\n min-width: 44px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-number-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-number-label\");\n\n const fieldRow = document.createElement(\"div\");\n fieldRow.classList.add(\"mljar-number-field-row\");\n\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.classList.add(\"mljar-number-input\");\n\n const decrementBtn = document.createElement(\"button\");\n decrementBtn.type = \"button\";\n decrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-down\");\n decrementBtn.textContent = \"-\";\n decrementBtn.setAttribute(\"aria-label\", \"Decrease value\");\n\n const incrementBtn = document.createElement(\"button\");\n incrementBtn.type = \"button\";\n incrementBtn.classList.add(\"mljar-number-step-btn\", \"mljar-number-step-up\");\n incrementBtn.textContent = \"+\";\n incrementBtn.setAttribute(\"aria-label\", \"Increase value\");\n\n const controls = document.createElement(\"div\");\n controls.classList.add(\"mljar-number-controls\");\n\n controls.appendChild(decrementBtn);\n controls.appendChild(incrementBtn);\n fieldRow.appendChild(input);\n fieldRow.appendChild(controls);\n\n container.appendChild(topLabel);\n container.appendChild(fieldRow);\n el.appendChild(container);\n\n function clamp(val, min, max) {\n if (Number.isFinite(min) && val < min) return min;\n if (Number.isFinite(max) && val > max) return max;\n return val;\n }\n\n function normalizeStep(step) {\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n function snapToStep(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = Math.round((value - base) / safeStep);\n const snapped = base + steps * safeStep;\n const precision = Math.max(\n 0,\n (String(safeStep).split(\".\")[1] || \"\").length\n );\n\n return Number(snapped.toFixed(precision + 2));\n }\n\n function isOnStepGrid(value, min, step) {\n const safeStep = normalizeStep(step);\n const base = Number.isFinite(min) ? min : 0;\n const steps = (value - base) / safeStep;\n const nearest = Math.round(steps);\n const epsilon = Math.max(1e-9, safeStep * 1e-9);\n\n return Math.abs(steps - nearest) <= epsilon;\n }\n\n function getCurrentBounds() {\n return {\n min: Number(model.get(\"min\")),\n max: Number(model.get(\"max\")),\n };\n }\n\n function isTransientDraft(raw) {\n return raw === \"\" || raw === \"-\" || raw === \".\" || raw === \"-.\";\n }\n\n let isEditing = false;\n const INPUT_COMMIT_DEBOUNCE_MS = 400;\n\n function clearPendingDraftCommit() {\n if (debounceTimer) clearTimeout(debounceTimer);\n pendingDraftValue = null;\n }\n\n function parseDraftValue(rawValue) {\n const raw = String(rawValue).trim();\n if (isTransientDraft(raw)) {\n return { kind: \"transient\" };\n }\n\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { kind: \"invalid\" };\n }\n\n return { kind: \"number\", value };\n }\n\n function commitValue(nextValue, saveNow = true) {\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n const parsed = parseDraftValue(nextValue);\n if (parsed.kind !== \"number\") {\n syncFromModel();\n return;\n }\n\n let v = parsed.value;\n v = clamp(v, min, max);\n v = snapToStep(v, min, step);\n v = clamp(v, min, max);\n input.value = String(v);\n model.set(\"value\", v);\n\n if (saveNow) {\n model.save_changes();\n }\n }\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter number\";\n\n const min = Number(model.get(\"min\"));\n const max = Number(model.get(\"max\"));\n const step = Number(model.get(\"step\"));\n\n if (Number.isFinite(min)) input.min = String(min); else input.removeAttribute(\"min\");\n if (Number.isFinite(max)) input.max = String(max); else input.removeAttribute(\"max\");\n if (Number.isFinite(step)) input.step = String(step); else input.removeAttribute(\"step\");\n\n const v = Number(model.get(\"value\"));\n if (!isEditing) {\n input.value = Number.isFinite(v) ? String(v) : \"\";\n }\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n incrementBtn.disabled = disabled;\n decrementBtn.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n let debounceTimer = null;\n let pendingDraftValue = null;\n input.addEventListener(\"focus\", () => {\n isEditing = true;\n });\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n\n const parsed = parseDraftValue(input.value);\n if (parsed.kind !== \"number\") {\n clearPendingDraftCommit();\n return;\n }\n\n const v = parsed.value;\n const { min, max } = getCurrentBounds();\n const step = Number(model.get(\"step\"));\n if (Number.isFinite(min) && v < min) {\n clearPendingDraftCommit();\n return;\n }\n if (Number.isFinite(max) && v > max) {\n clearPendingDraftCommit();\n return;\n }\n if (!isOnStepGrid(v, min, step)) {\n clearPendingDraftCommit();\n return;\n }\n\n pendingDraftValue = v;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n if (pendingDraftValue === null) return;\n model.set(\"value\", pendingDraftValue);\n model.save_changes();\n pendingDraftValue = null;\n }, INPUT_COMMIT_DEBOUNCE_MS);\n });\n\n input.addEventListener(\"blur\", () => {\n isEditing = false;\n clearPendingDraftCommit();\n commitValue(input.value, true);\n });\n\n input.addEventListener(\"keydown\", event => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n input.blur();\n }\n });\n\n incrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base + step, min, step));\n });\n\n decrementBtn.addEventListener(\"click\", () => {\n if (model.get(\"disabled\")) return;\n const current = Number(model.get(\"value\"));\n const step = normalizeStep(Number(model.get(\"step\")));\n const min = Number(model.get(\"min\"));\n const base = Number.isFinite(current) ? current : 0;\n commitValue(snapToStep(base - step, min, step));\n });\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:min\", syncFromModel);\n model.on(\"change:max\", syncFromModel);\n model.on(\"change:step\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n // ---- read cell id (no DOM modifications) ----\n /*\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }*/\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Agent headcount",
"layout": "IPY_MODEL_b4527b9783fe43598a8d5846ac38e606",
"layout_path": null,
"max": 100000.0,
"min": 0.0,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"step": 10.0,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": 450.0
}
},
"fd25d64cd05848d7958943957f7bd4a8": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"_model_module": "@jupyter-widgets/base",
"_model_module_version": "2.0.0",
"_model_name": "LayoutModel",
"_view_count": null,
"_view_module": "@jupyter-widgets/base",
"_view_module_version": "2.0.0",
"_view_name": "LayoutView",
"align_content": null,
"align_items": null,
"align_self": null,
"border_bottom": null,
"border_left": null,
"border_right": null,
"border_top": null,
"bottom": null,
"display": null,
"flex": null,
"flex_flow": null,
"grid_area": null,
"grid_auto_columns": null,
"grid_auto_flow": null,
"grid_auto_rows": null,
"grid_column": null,
"grid_gap": null,
"grid_row": null,
"grid_template_areas": null,
"grid_template_columns": null,
"grid_template_rows": null,
"height": null,
"justify_content": null,
"justify_items": null,
"left": null,
"margin": null,
"max_height": null,
"max_width": null,
"min_height": null,
"min_width": null,
"object_fit": null,
"object_position": null,
"order": null,
"overflow": null,
"padding": null,
"right": null,
"top": null,
"visibility": null,
"width": null
}
},
"ff4373a0dfc347d09f933f0e101f3243": {
"model_module": "anywidget",
"model_module_version": "~0.11.*",
"model_name": "AnyModel",
"state": {
"_anywidget_id": "mercury.text.TextInputWidget",
"_css": "\n .mljar-textinput-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n min-width: 120px;\n font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n font-weight: normal;\n color: #0f172a;\n padding-left: 4px;\n padding-right: 4px;\n box-sizing: border-box;\n }\n\n .mljar-textinput-top-label {\n padding-top: 6px;\n margin-bottom: 6px;\n text-align: left;\n width: 100%;\n font-weight: 600;\n }\n\n .mljar-textinput-input {\n width: 100%;\n min-height: 40px;\n padding: 9px 10px;\n box-sizing: border-box;\n border: 1px solid #cfd1d5;\n border-radius: 6px;\n background: #ffffff;\n color: #0f172a;\n line-height: 1.4;\n\n appearance: none !important;\n background-color: #ffffff !important;\n }\n\n .mljar-textinput-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: none;\n }\n\n .mljar-textinput-input:disabled {\n background: #f5f5f5;\n color: #888;\n cursor: not-allowed;\n }\n\n @media (max-width: 768px) {\n .mljar-textinput-input {\n min-height: 44px;\n padding: 10px 12px;\n }\n }\n ",
"_dom_classes": [],
"_esm": "\n function render({ model, el }) {\n const container = document.createElement(\"div\");\n container.classList.add(\"mljar-textinput-container\");\n\n const topLabel = document.createElement(\"div\");\n topLabel.classList.add(\"mljar-textinput-top-label\");\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.classList.add(\"mljar-textinput-input\");\n\n container.appendChild(topLabel);\n container.appendChild(input);\n el.appendChild(container);\n\n let debounceTimer = null;\n\n input.addEventListener(\"input\", () => {\n if (model.get(\"disabled\")) return;\n model.set(\"value\", input.value);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => model.save_changes(), 200);\n });\n\n function syncFromModel() {\n topLabel.innerHTML = model.get(\"label\") || \"Enter text\";\n input.value = model.get(\"value\") ?? \"\";\n\n const disabled = !!model.get(\"disabled\");\n input.disabled = disabled;\n\n const hidden = !!model.get(\"hidden\");\n container.style.display = hidden ? \"none\" : \"flex\";\n }\n\n model.on(\"change:value\", syncFromModel);\n model.on(\"change:label\", syncFromModel);\n model.on(\"change:disabled\", syncFromModel);\n model.on(\"change:hidden\", syncFromModel);\n\n syncFromModel();\n\n /*\n // ---- read cell id (no DOM modifications) ----\n const ID_ATTR = \"data-cell-id\";\n const hostWithId = el.closest(`[${ID_ATTR}]`);\n const cellId = hostWithId ? hostWithId.getAttribute(ID_ATTR) : null;\n\n if (cellId) {\n model.set(\"cell_id\", cellId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: cellId });\n } else {\n const mo = new MutationObserver(() => {\n const host = el.closest(`[${ID_ATTR}]`);\n const newId = host?.getAttribute(ID_ATTR);\n if (newId) {\n model.set(\"cell_id\", newId);\n model.save_changes();\n model.send({ type: \"cell_id_detected\", value: newId });\n mo.disconnect();\n }\n });\n mo.observe(document.body, { attributes: true, subtree: true, attributeFilter: [ID_ATTR] });\n }\n */\n }\n export default { render };\n ",
"_model_module": "anywidget",
"_model_module_version": "~0.11.*",
"_model_name": "AnyModel",
"_view_count": null,
"_view_module": "anywidget",
"_view_module_version": "~0.11.*",
"_view_name": "AnyView",
"cell_id": "",
"disabled": false,
"hidden": false,
"label": "Client name",
"layout": "IPY_MODEL_1e1189045b604913a5383ec4b05aff36",
"layout_path": null,
"position": "sidebar",
"render_slot_id": null,
"source_cell_id": null,
"tabbable": null,
"tooltip": null,
"url_key": "",
"value": "Acme Demo Co"
}
}
},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}