import React, { useState, useEffect, useMemo, useRef } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';

/* ==================================================================== */
/*  YOUR SETTINGS — edit these four lines, rebuild, redeploy.           */
/* ==================================================================== */
const CONFIG = {
  brandName:   'AI Readiness Compass',
  siteUrl:     'https://aireadinesscompass.de',
  contactEmail:'hello@aireadinesscompass.de',

  // Where "Book a Call" sends people. Replace with your Cal.com / Calendly link.
  bookingUrl:  'https://calendar.app.google/dwaLWoKd9hrNwgb17',

  // Legal pages (shipped in /public, served at these paths).
  privacyUrl:   'privacy.html',
  imprintUrl:   'imprint.html',

  // Hero artwork. Drop your own file into /public and name it here.
  // If the file is missing, the built-in illustration is drawn instead.
  heroImage:    'hero.png',

};

/* ------------------------------------------------------------------ */
/*  STATIC CONFIG                                                       */
/* ------------------------------------------------------------------ */

const TIERS = [
  { key:'foundation',   min:0,  max:25,  label:'Foundation Required',  color:'#8F3D2A', desc:'Fragmented systems, no APIs, manual processes. Connect core systems before any AI.' },
  { key:'awareness',    min:26, max:45,  label:'Awareness Phase',      color:'#A35139', desc:'Some digital tools, patchy connectivity. Focus on API enablement and data cleanup.' },
  { key:'integration',  min:46, max:65,  label:'Integration Phase',    color:'#8A6A2E', desc:'APIs present, partial middleware. Ready for guarded pilot AI use cases.' },
  { key:'optimisation', min:66, max:80,  label:'Optimisation Phase',   color:'#3D6B5A', desc:'Strong integration layer, good data quality. Ready for agents on defined workflows.' },
  { key:'agentReady',   min:81, max:100, label:'Agent Ready',          color:'#2E6B45', desc:'Full integration maturity and governance. Deploy MCP servers and multi-agent orchestration.' },
];
const tierFor = (s) => TIERS.find(t => s >= t.min && s <= t.max) || TIERS[0];

const INDUSTRIES = ['Healthcare','Manufacturing / Industrial','Financial Services','Retail / E-Commerce','Professional Services','SaaS / Technology','Logistics & Supply Chain','Public Sector / NGO','Other'];
const COMPANY_SIZES = ['1–10 employees','11–50','51–200','201–500','500+'];
const IT_FUNCTIONS = ['Own internal IT team','IT outsourced to a partner','Handled by individual team members','No IT function'];

const PERSONAS = {
  it:   { key:'it',   title:'IT / Technical',        roles:'IT Manager · System Architect · Developer · CTO', blurb:'I want technical depth and specific integration architecture guidance.', icon:'code' },
  exec: { key:'exec', title:'Leadership / Strategic', roles:'CEO · CDO · COO · Board Member',                  blurb:'I want the business impact, ROI, and a strategic roadmap.',            icon:'briefcase' },
  ops:  { key:'ops',  title:'Functional / Operational', roles:'Sales · Marketing · Operations · Customer Success', blurb:'I want to know which of my daily tools and workflows AI can improve.', icon:'chart' },
};

/* Ordered so the most AI-relevant question comes first and the rest follows
   how a business actually thinks about its tools. Everything defaults to None. */
const CATEGORIES = [
  // — The subject of the assessment, so it leads —
  { key:'ai',      name:'AI & LLM Tools',              group:'AI you already use', highlight:true,
    hint:'Whatever your teams already use, officially or not — this is the starting point for everything else.',
    tools:['ChatGPT (OpenAI)','Claude (Anthropic)','Google Gemini','Microsoft Copilot','Mistral','Perplexity','Internal / custom LLM'] },

  // — The suite almost everyone runs —
  { key:'suite',   name:'Workplace Suite (email, files, chat)', group:'Everyday workplace',
    hint:'The platform your company runs on day to day — email, documents, calendar and chat.',
    tools:['Microsoft 365','Google Workspace','Microsoft Teams','Slack','Zoom','Notion','Other / on-premise email'] },

  // — Systems that run the business —
  { key:'crm',     name:'CRM',                         group:'Core business systems', tools:['Salesforce','SAP','HubSpot','Zoho CRM','Odoo','Pipedrive','Microsoft Dynamics','Freshsales'] },
  { key:'erp',     name:'ERP',                         group:'Core business systems', tools:['SAP S/4HANA','SAP Business One','Microsoft Dynamics 365','ProAlpha','Xentral','Sage','Lexware','Odoo'] },
  { key:'ehr',     name:'EHR (Healthcare)',            group:'Core business systems', tools:['Systmia','Meditec','EPIKUR','Orbis','CGM M1'], industry:'Healthcare' },
  { key:'finance', name:'Finance & Accounting',        group:'Core business systems', tools:['DATEV','Lexware','SAP FI','Candis','Spendesk'] },

  // — Winning and serving customers —
  { key:'service', name:'Service & Support',           group:'Customer-facing tools', tools:['Zendesk','Intercom','Freshdesk','Salesforce Service Cloud','Drift'] },
  { key:'marketing',name:'Marketing & Outreach',       group:'Customer-facing tools', tools:['HubSpot Marketing','Marketo','Mailchimp','Outreach.io','Salesloft','Apollo','lemlist','Gong'] },
  { key:'web',     name:'Website & E-Commerce',        group:'Customer-facing tools', tools:['Shopify','WooCommerce','Magento','Custom-built (WordPress etc.)'] },

  // — Getting work done —
  { key:'pm',      name:'Project & Task Management',   group:'Getting work done', tools:['Asana','Monday.com','Jira','ClickUp','Trello','Notion'] },
  { key:'hr',      name:'HR & People',                 group:'Getting work done', tools:['Personio','Workday','BambooHR','SAP SuccessFactors','DATEV Lohn'] },

  // — Where the data lives —
  { key:'dwh',     name:'Data Warehouse / Lakehouse',  group:'Where your data lives', tools:['Snowflake','Databricks','Google BigQuery','Amazon Redshift','Azure Synapse'] },
  { key:'lake',    name:'Data Lake / Storage',         group:'Where your data lives', tools:['Azure Data Lake','AWS S3','Snowflake','Google Cloud Storage','On-premise file server'] },
  { key:'sheets',  name:'Spreadsheets as a system of record', group:'Where your data lives',
    hint:'Only tick these if a spreadsheet is where the real answer lives — not just for reporting.',
    tools:['Excel','Google Sheets'] },

  // — Everything else —
  { key:'iot',     name:'Machines & IoT Systems',      group:'Specialised & legacy',
    hint:'Anything physical that produces data — you don\u2019t need to know the technology behind it.',
    tools:['Production or shop-floor machines','Sensors / measuring devices','Vehicles / fleet','Building or facility systems (heating, access, energy)','Machine control system (PLC / SCADA)','We have machines, but I don\u2019t know what runs them'] },
  { key:'legacy',  name:'Legacy / Custom Systems',     group:'Specialised & legacy', tools:['Internal custom-built tool','Mainframe','Home-grown database','Industry-specific software'] },
  { key:'mobile',  name:'Mobile Apps',                 group:'Specialised & legacy', tools:['Custom iOS/Android app','Progressive Web App'] },
  { key:'other',   name:'Other Tools',                 group:'Specialised & legacy', tools:[] },
];

const CONNECTIONS = [
  { key:'none',     label:'Not connected',            color:'#8F3D2A' },
  { key:'manual',   label:'Manual export (CSV/Excel)',color:'#A35139' },
  { key:'scheduled',label:'Automated but scheduled',  color:'#8A6A2E' },
  { key:'realtime', label:'Real-time (API)',          color:'#2E6B45' },
];
const connMeta = (k) => CONNECTIONS.find(c => c.key === k) || CONNECTIONS[0];

/* Ranked from the smallest, most contained scope to the broadest. */
const AI_GOALS = [
  { id:'data', scope:'Focused scope',   it:'Automated data pipelines & insights',  biz:'Automated reporting, insights & anomaly detection' },
  { id:'emp',  scope:'Internal scope',  it:'Internal knowledge / workflow agent',  biz:'Internal AI — automate workflows' },
  { id:'cx',   scope:'External scope',  it:'Customer-facing API automation',       biz:'Customer-facing AI (service, sales qualification, onboarding)' },
  { id:'360',  scope:'Company-wide',    it:'End-to-end agent orchestration',       biz:'Full-landscape AI across systems & departments' },
  { id:'unsure', scope:'Not sure yet',  it:'Exploring options',                    biz:"I'm not sure yet — guide me" },
];

const AMBITION = [
  { lvl:1, name:'L1 · Assist',      desc:'Simple chatbot / FAQ automation on our website or helpdesk.' },
  { lvl:2, name:'L2 · Answer',      desc:'AI answers questions using our internal business data.' },
  { lvl:3, name:'L3 · Act',         desc:'AI takes single actions — updates records, sends notifications, books slots.' },
  { lvl:4, name:'L4 · Automate',    desc:'Automated multi-step workflows; AI handles exceptions end-to-end.' },
  { lvl:5, name:'L5 · Orchestrate', desc:'Fully autonomous agents collaborating across all systems, minimal oversight.' },
  { lvl:0, name:'Unsure',           desc:"I'd like help understanding what's possible." },
];

/* Automation / integration platforms, grouped by how much governance they give
   you. `tier` feeds the integration score, so it works for every persona — not
   just the technical one. */
const AUTOMATION_TOOLS = [
  { name:'n8n',                      tier:'light' },
  { name:'Make (Integromat)',        tier:'light' },
  { name:'Zapier',                   tier:'light' },
  { name:'Microsoft Power Automate', tier:'light' },
  { name:'MuleSoft Anypoint',        tier:'enterprise' },
  { name:'Workato',                  tier:'enterprise' },
  { name:'Dell Boomi',               tier:'enterprise' },
  { name:'Lobster_data',             tier:'enterprise' },
  { name:'SAP Integration Suite',    tier:'enterprise' },
  { name:'Azure Integration Services',tier:'enterprise' },
  { name:'AWS EventBridge',          tier:'enterprise' },
  { name:'Talend',                   tier:'enterprise' },
  { name:'Claude (Anthropic)',       tier:'agent' },
  { name:'ChatGPT / OpenAI agents',  tier:'agent' },
  { name:'Custom scripts built in-house', tier:'custom' },
];
const toolTier = (n) => (AUTOMATION_TOOLS.find(t => t.name === n) || {}).tier || 'custom';

/* Controls that keep AI safe and affordable. Absence of these drives the
   security section on the results page. */
const AI_GUARDRAILS = [
  'Limits on AI cost / token consumption',
  'Rules on which data AI may and may not access',
  'Masking or removal of personal data before AI sees it',
  'A data processing agreement (AVV/DPA) with our AI provider',
  'API rules — rate limiting, OAuth scopes, access keys',
  'Logging of what the AI did (audit trail)',
];

const TIMELINES = ['Within 3 months (quick wins)','3–12 months (structured project)','12–24 months (transformation programme)','No specific timeline yet'];
const BUDGETS = ['Under €10.000','€10.000 – €50.000','€50.000 – €100.000','€100.000 – €250.000','Over €250.000','Not defined yet'];

const DATA_TYPES = ['Customer & contact data','Product & catalogue data','Order & transactional data','Machine & IoT sensor data','Financial & accounting data','Employee & HR data','Unstructured documents (contracts, emails, PDFs)','Media (images, videos)'];
const STRUCTURE = ['Mostly structured — tables, databases, well-organised spreadsheets','A mix — some structured, some documents and free text','Mostly unstructured — documents, emails, PDFs, conversation logs'];
const DATA_ENTRY = ['Manually entered by employees','Via web forms or customer portals','Automatically from other integrated tools','Via email (processed manually or semi-automatically)','Via file uploads (CSV, Excel, PDF)','Via IoT / sensor feeds','Via third-party data providers'];

/* Industries where the data itself raises the bar. Deliberately specific — a
   generic "mind the GDPR" line is useless to someone running a clinic. */
const INDUSTRY_RULES = {
  'Healthcare': {
    label: 'patient data',
    intro: 'Health data is a special category under Art. 9 GDPR: processing is prohibited unless a specific exception applies. AI that touches patient records raises the bar considerably.',
    points: [
      ['GDPR Art. 9 — special-category data', 'Health data needs an explicit legal basis. Feeding it to a general-purpose AI service without one is a breach, however useful the output.'],
      ['Professional confidentiality (§ 203 StGB in Germany)', 'Disclosing patient information to an external processor — including a cloud AI provider — can be a criminal offence without a proper contract and safeguards.'],
      ['EU AI Act — high-risk classification', 'AI used for triage, diagnosis support or care decisions is likely high-risk: risk management, logging, human oversight and technical documentation become mandatory.'],
      ['Medical device rules (MDR)', 'Software that informs diagnosis or treatment may itself qualify as a medical device and need conformity assessment before use.'],
      ['Pseudonymisation and masking', 'Strip or mask identifiers before any model sees the record. This is the single most effective control, and it needs a place to run — the gateway.'],
    ],
  },
  'Financial Services': {
    label: 'financial and customer data',
    intro: 'Financial services carry supervisory obligations on top of GDPR — regulators expect you to demonstrate control, not just claim it.',
    points: [
      ['DORA — digital operational resilience', 'ICT risk management, incident reporting and oversight of third-party providers (which includes AI vendors) are now explicit obligations.'],
      ['EU AI Act — creditworthiness is high-risk', 'AI used to assess credit or price risk is classified high-risk: documentation, human oversight, bias testing and logging are required.'],
      ['BaFin / MaRisk and outsourcing rules', 'Using an external AI service is an outsourcing arrangement. It needs a register entry, a risk assessment and audit rights.'],
      ['Auditability and data lineage', 'You must be able to reconstruct which data produced which decision, months later. That is impossible without centralised logging.'],
      ['AML / KYC data handling', 'Anti-money-laundering data has its own retention and confidentiality rules that AI access must not quietly circumvent.'],
    ],
  },
  'Public Sector / NGO': {
    label: 'citizen data',
    intro: 'Public bodies are held to a higher transparency standard, and several AI uses are restricted outright.',
    points: [
      ['EU AI Act — prohibited and high-risk uses', 'Social scoring is banned; AI in essential public services, benefits or law enforcement is high-risk with strict obligations.'],
      ['Transparency and explainability', 'Citizens affected by an automated decision have a right to a meaningful explanation of it.'],
      ['Procurement and vendor lock-in', 'Public procurement rules constrain how AI services can be bought, and favour portability.'],
      ['Records management', 'Statutory retention and archiving duties apply to AI-assisted correspondence and decisions too.'],
    ],
  },
};

/* Pick the phrasing that matches whoever is reading the report. */
const byRole = (persona, o) => o[persona] || o.exec;

/* What an AI Gateway covers — the five that matter most, said three ways. */
const GATEWAY_COVERS = [
  {
    icon: 'lock',
    title: { it:'Access & identity', exec:'Who is allowed to do what', ops:'Who is allowed to do what' },
    body: {
      it:  'Authentication and authorisation for which agent, app or user may call which models and tools, with least-privilege scoping and central credential rotation. Identity context propagates through agent-to-agent and agent-to-tool calls, so "who did this, on whose behalf" survives several delegations from the original user.',
      exec:'One place that decides which AI may reach which system, and with what permissions. Access is granted deliberately rather than by whoever set the tool up — and it stays traceable even when one agent hands work to another.',
      ops: 'Control over which AI tool can see which of your systems. An assistant that helps with support tickets does not automatically get to see payroll.',
    },
  },
  {
    icon: 'trending',
    title: { it:'Cost & token control', exec:'Predictable spend', ops:'No surprise bills' },
    body: {
      it:  'Real-time token telemetry per LLM call with quotas and budget caps per team, app or use case, plus cost estimation per model and provider. Caching of repeated prompts removes redundant calls at the protocol level, without touching agent code.',
      exec:'AI spend is capped and attributed per team or use case, so cost is a budget line you set rather than an invoice you discover. Caching and routing cut the bill without any change to the applications themselves.',
      ops: 'One place to see what every AI initiative is actually costing, in near real time — no waiting for a monthly bill to find out spend ran high.',
    },
  },
  {
    icon: 'shield',
    title: { it:'Data protection', exec:'Sensitive data stays protected', ops:'Customer data stays protected' },
    body: {
      it:  'PII detection and redaction on both input and output, content and policy filtering, prompt-injection and jailbreak detection, plus data-residency routing where regulation requires it.',
      exec:'Personal and confidential data is detected and masked before it reaches a model, and responses are checked on the way back. This is what makes AI defensible under GDPR and the EU AI Act.',
      ops: 'Customer details are stripped or masked before an AI sees them, so using AI does not mean handing your customer list to an outside service.',
    },
  },
  {
    icon: 'database',
    title: { it:'Audit logging', exec:'Provable oversight', ops:'A record of what happened' },
    body: {
      it:  'Correlation IDs follow a request across API calls, tool invocations and agent-to-agent delegations, so one trace tells the whole story of a transaction. Retention policies applied centrally rather than per tool.',
      exec:'A complete, queryable record of what AI did in your business. When a customer, an auditor or a regulator asks, you can answer with evidence rather than assurance.',
      ops: 'A clear trail of every AI-driven action — useful for troubleshooting when something goes wrong, and for showing auditors what happened.',
    },
  },
  {
    icon: 'link',
    title: { it:'Model routing & resilience', exec:'No lock-in, no outages', ops:'It keeps working' },
    body: {
      it:  'One API surface across providers so switching or A/B testing needs no orchestration rewrite, with version pinning, gradual rollout and fallback routing. Existing API endpoints can also be exposed as governed, authenticated agent tools, turning API investment you already made into an agent-ready library.',
      exec:'You are not locked to one AI vendor: models can be swapped, compared on price and quality, or failed over without rebuilding anything — which matters in a model market that moves this fast.',
      ops: 'If one AI provider goes down or gets slow, work carries on through another — and you are never stuck with one supplier.',
    },
  },
];

const GLOSSARY = {
  API:'A standard way for two software systems to exchange data automatically — like a waiter carrying your order to the kitchen.',
  middleware:'Software that sits between your apps and manages how they share data — the connective tissue of your IT landscape.',
  'integration layer':'One governed place where systems connect, data is cleaned and trusted, and security is applied consistently — the foundation AI acts on.',
  'MCP server':'A Model Context Protocol server — a standard, secure gateway that lets AI models read and act on data from your business systems.',
  MDM:'Master Data Management — keeping one trusted record for key data (one "true" customer instead of five slightly different ones).',
  'real-time':'Data moves between systems the instant something happens, not in once-a-day batches.',
  'AI agent':'An AI that takes autonomous actions — not just answering, but updating records and triggering workflows.',
};

/* Each stage carries its own shade — a journey from navy (who you are)
   through amber (how you work) to green (your result). */
const STEPS = [
  { label:'Company',      icon:'building', color:'#1B2632' },
  { label:'Role',         icon:'user',     color:'#35506B' },
  { label:'Vision',       icon:'target',   color:'#3D6B5A' },
  { label:'Systems',      icon:'grid',     color:'#6E7357' },
  { label:'Connectivity', icon:'link',     color:'#8A6A2E' },
  { label:'Data',         icon:'database', color:'#A35139' },
  { label:'Automation',   icon:'zap',      color:'#C0662F' },
  { label:'Results',      icon:'award',    color:'#2E6B45' },
];

/* ------------------------------------------------------------------ */
/*  SMALL UI PRIMITIVES                                                 */
/* ------------------------------------------------------------------ */

const Tip = ({ term, children, show }) => {
  if (!show || !GLOSSARY[term]) return <>{children}</>;
  return <span className="tt">{children}<span>{GLOSSARY[term]}</span></span>;
};

/* Click-to-open "?" explainer — works on touch, unlike hover tooltips. */
function Help({ title, children, label='What does this mean?' }) {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={()=>setOpen(o=>!o)} aria-expanded={open} aria-label={label}
        className={`no-print ml-1.5 inline-flex h-5 w-5 shrink-0 translate-y-[1px] items-center justify-center rounded-full border text-[11px] font-bold transition
          ${open ? 'border-amber-500 bg-amber-500 text-navy' : 'border-slate-300 bg-white text-slate-500 hover:border-amber-500 hover:text-amber-600'}`}>
        ?
      </button>
      {open && (
        <div className="mt-2 rounded-xl border border-amber-200 bg-amber-50 p-3 text-sm font-normal text-slate-700">
          {title && <div className="mb-1 font-bold text-navy">{title}</div>}
          {children}
        </div>
      )}
    </>
  );
}

const MCP_EXPLAINER = (
  <>
    <p>
      <b>MCP (Model Context Protocol)</b> is simply an agreed standard for how an AI
      assistant connects to your business systems — think of it as a{' '}
      <b>secure power socket for AI</b>.
    </p>
    <p className="mt-2">
      An <b>MCP server</b> is the socket you install. Instead of building a custom
      connection for every AI tool you ever try, you open <b>one controlled doorway</b>,
      and any AI can plug into it — while you decide exactly which data it may see and
      which actions it may take. Everything it does can be logged.
    </p>
    <p className="mt-2">
      <b>In practice:</b> it's what lets an assistant answer "what's the status of order
      1234?" from your real system instead of guessing — and, when you allow it, update
      that order too.
    </p>
  </>
);

const Field = ({ label, children, missing }) => (
  <label className="block mb-4" data-missing={missing ? 'true' : undefined}>
    <span className="block text-sm font-semibold text-navy mb-1.5">{label}</span>
    {children}
  </label>
);

const inputCls = "w-full rounded-xl border border-slate-300 bg-white px-4 py-2.5 text-navy placeholder-slate-400 focus:border-amber-500 focus:ring-2 focus:ring-amber-500/30 outline-none transition";

const Btn = ({ children, onClick, disabled, variant='primary', className='' }) => {
  const base = "inline-flex items-center justify-center gap-2 rounded-xl px-5 py-2.5 font-semibold transition disabled:opacity-40 disabled:cursor-not-allowed";
  const styles = {
    primary: "bg-amber-500 text-navy hover:bg-amber-400 shadow-sm shadow-amber-500/30",
    ghost:   "bg-transparent text-navy border border-slate-300 hover:border-navy",
    navy:    "bg-navy text-white hover:bg-navy-700",
  }[variant];
  return <button onClick={onClick} disabled={disabled} className={`${base} ${styles} ${className}`}>{children}</button>;
};

const Choice = ({ selected, onClick, children, className='' }) => (
  <button onClick={onClick}
    className={`text-left w-full rounded-xl border-2 px-4 py-3 transition ${selected ? 'border-amber-500 bg-amber-50' : 'border-slate-200 bg-white hover:border-slate-300'} ${className}`}>
    {children}
  </button>
);

const Radio = ({ options, value, onChange, cols=1 }) => (
  <div className={`grid gap-2 ${cols===2?'sm:grid-cols-2':''}`}>
    {options.map(o => (
      <Choice key={o} selected={value===o} onClick={()=>onChange(o)}>
        <span className={`text-sm ${value===o?'font-semibold text-navy':'text-slate-700'}`}>{o}</span>
      </Choice>
    ))}
  </div>
);

const MultiCheck = ({ options, values, onToggle, cols=1 }) => (
  <div className={`grid gap-2 ${cols===2?'sm:grid-cols-2':''}`}>
    {options.map(o => {
      const on = values.includes(o);
      return (
        <button key={o} onClick={()=>onToggle(o)}
          className={`flex items-start gap-2.5 text-left rounded-xl border-2 px-4 py-2.5 transition ${on?'border-amber-500 bg-amber-50':'border-slate-200 bg-white hover:border-slate-300'}`}>
          <span className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border-2 ${on?'border-amber-500 bg-amber-500':'border-slate-300'}`}>
            {on && <svg width="10" height="10" viewBox="0 0 12 12"><path d="M2 6l3 3 5-6" stroke="#1B2632" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>}
          </span>
          <span className={`text-sm ${on?'font-semibold text-navy':'text-slate-700'}`}>{o}</span>
        </button>
      );
    })}
  </div>
);

const ICON_PATHS = {
  code:      'M8 6l-5 6 5 6M16 6l5 6-5 6',
  briefcase: 'M4 8h16v11H4zM9 8V5h6v3',
  chart:     'M4 20V10M10 20V4M16 20v-7M22 20H2',
  building:  'M3 21h18M5 21V5a1 1 0 011-1h7a1 1 0 011 1v16M14 21V9h4a1 1 0 011 1v11M8 8h3M8 12h3M8 16h3',
  user:      'M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2M12 11a4 4 0 100-8 4 4 0 000 8',
  target:    'M12 21a9 9 0 100-18 9 9 0 000 18M12 17a5 5 0 100-10 5 5 0 000 10M12 13a1 1 0 100-2 1 1 0 000 2',
  grid:      'M4 4h6v6H4zM14 4h6v6h-6zM14 14h6v6h-6zM4 14h6v6H4z',
  link:      'M10 13a5 5 0 007.5.5l2-2a5 5 0 00-7-7l-1 1M14 11a5 5 0 00-7.5-.5l-2 2a5 5 0 007 7l1-1',
  database:  'M12 8c4.4 0 8-1.3 8-3s-3.6-3-8-3-8 1.3-8 3 3.6 3 8 3zM4 5v14c0 1.7 3.6 3 8 3s8-1.3 8-3V5M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3',
  zap:       'M13 2L4 14h7l-1 8 9-12h-7l1-8z',
  award:     'M12 15a6 6 0 100-12 6 6 0 000 12M8.5 14L7 22l5-2.5L17 22l-1.5-8',
  shield:    'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z',
  plug:      'M9 2v6M15 2v6M6 8h12v3a6 6 0 01-12 0V8zM12 17v5',
  lock:      'M5 11h14v10H5zM8 11V7a4 4 0 018 0v4',
  trending:  'M3 17l6-6 4 4 8-8M15 7h6v6',
  layers:    'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5',
  compass:   'M12 22a10 10 0 100-20 10 10 0 000 20M16 8l-2.5 5.5L8 16l2.5-5.5L16 8z',
};

const Icon = ({ name, size=22, color='currentColor', strokeWidth=1.8, className='' }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color}
    strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
    <path d={ICON_PATHS[name] || ''} />
  </svg>
);

/* ------------------------------------------------------------------ */
/*  SCORING ENGINE                                                      */
/* ------------------------------------------------------------------ */

function allSystems(systems) {
  const out = [];
  CATEGORIES.forEach(cat => {
    const s = systems[cat.key];
    if (!s || s.notInUse) return;
    Object.entries(s.items || {}).forEach(([name, v]) => out.push({ cat: cat.key, name, ...v }));
  });
  return out;
}

function calculateScore(a) {
  const sys = allSystems(a.systems);
  const nonSheet = sys.filter(s => s.cat !== 'sheets');
  const connected = sys.filter(s => s.connection === 'scheduled' || s.connection === 'realtime');
  const anyRealtime = sys.some(s => s.connection === 'realtime');
  const anyScheduled = sys.some(s => s.connection === 'scheduled');
  const trustVals = sys.map(s => s.trust).filter(Boolean);
  const avgTrust = trustVals.length ? trustVals.reduce((x,y)=>x+y,0)/trustVals.length : 0;

  /* ---- Integration (0–25) ---- */
  let mwPts = 0, apiPts = 0, rtPts = 0, connPts = 0;
  const p = a.persona;

  /* The integration-platform question is asked of every persona, so it is the
     most reliable middleware signal we have. Owning one is a real head start
     and is scored generously. */
  const tools = a.c_tools || [];
  const toolMw = tools.some(t => toolTier(t) === 'enterprise') ? 12
               : tools.some(t => toolTier(t) === 'light')      ? 7
               : tools.some(t => toolTier(t) === 'custom')     ? 3
               : tools.some(t => toolTier(t) === 'agent')      ? 2
               : 0;
  if (p === 'it') {
    const types = (a.c_apiTypes||[]).filter(t => t !== 'No APIs in use');
    apiPts = types.length === 0 ? 0 : types.length === 1 ? 4 : 8;
    rtPts = { 'Yes — across most systems':7, 'Yes — in limited areas':5, 'Batch / scheduled only':3, 'No':0, 'Unsure':0 }[a.c_realtime] || 0;
  } else if (p === 'exec') {
    mwPts = { manual:0, patchy:4, most:6, realtime:10 }[a.c_share] || 0;
    apiPts = anyRealtime ? 8 : anyScheduled ? 4 : 0;
    rtPts = { manual:0, patchy:3, most:5, realtime:7 }[a.c_share] || 0;
  } else {
    mwPts = { manual:0, semi:4, auto:6, none:0 }[a.c_lead] || 0;
    apiPts = anyRealtime ? 8 : anyScheduled ? 4 : 0;
    rtPts = anyRealtime ? 6 : anyScheduled ? 3 : 0;
  }
  mwPts = Math.max(mwPts, toolMw);
  connPts = connected.length === 0 ? 0 : connected.length <= 3 ? 2 : connected.length <= 6 ? 4 : 6;
  const integration = Math.min(25, mwPts + apiPts + rtPts + connPts);

  /* ---- Data (0–20) ---- */
  const trustPts = (avgTrust/5)*8;
  const structPts = a.d_structure === STRUCTURE[0] ? 4 : a.d_structure === STRUCTURE[1] ? 2 : 0;
  let govPts = 0, mdmPts = 0;
  if (p === 'it') {
    govPts = { formal:4, informal:2, partial:1, no:0 }[a.d_gov] || 0;
    mdmPts = { yes:4, planning:2, partial:1, no:0 }[a.d_mdm] || 0;
  } else if (p === 'exec') {
    govPts = { very:4, fairly:2, mixed:1, not:0 }[a.d_confidence] || 0;
    mdmPts = { very:2, fairly:1, mixed:1, not:0 }[a.d_confidence] || 0;
  } else {
    govPts = { rarely:3, sometimes:2, frequently:1, daily:0 }[a.d_conflict] || 0;
    mdmPts = { rarely:2, sometimes:1, frequently:0, daily:0 }[a.d_conflict] || 0;
  }
  const data = Math.min(20, trustPts + structPts + govPts + mdmPts);

  /* ---- Automation (0–20) ---- */
  const wfPts = { extensive:10, some:8, few:4, no:0 }[a.au_workflows] || 0;
  const aiPts = { production:6, pilot:4, exploring:2, no:0 }[a.au_pilot] || 0;
  const livePts = { yes:4, partial:2, no:0, none:0 }[a.au_live] || 0;
  const automation = Math.min(20, wfPts + aiPts + livePts);

  /* ---- Systems (0–15) ---- */
  const cnt = nonSheet.length;
  let sysBase = cnt === 0 ? 0 : cnt <= 2 ? 3 : cnt <= 5 ? 7 : cnt <= 9 ? 11 : 15;
  const hasWhLake = sys.some(s => s.cat === 'dwh' || s.cat === 'lake');
  const noExcelPrimary = !(a.systems.sheets && !a.systems.sheets.notInUse && Object.keys(a.systems.sheets.items||{}).length);
  const systems = Math.min(15, sysBase + (hasWhLake?3:0) + (noExcelPrimary?2:0));

  /* ---- Strategy (0–10) ---- */
  const ambPts = { 1:2, 2:4, 3:6, 4:8, 5:10, 0:1 }[a.v_ambition] ?? 0;
  const budIdx = BUDGETS.indexOf(a.v_budget);
  const budPts = budIdx < 0 || a.v_budget === 'Not defined yet' ? 0 : budIdx === 0 ? 1 : budIdx <= 1 ? 3 : 4;
  const goalPts = (a.v_goals||[]).length >= 2 ? 2 : (a.v_goals||[]).length === 1 ? 1 : 0;
  const tlPts = (a.v_timeline && a.v_timeline !== 'No specific timeline yet') ? 1 : 0;
  const strategy = Math.min(10, ambPts + budPts + goalPts + tlPts);

  /* ---- Org (0–10) ---- */
  /* Team-readiness was dropped as a question, so IT capability now carries this
     dimension on its own and is rescaled to the full 10 points. */
  const itPts = { 'Own internal IT team':10, 'IT outsourced to a partner':6, 'Handled by individual team members':3, 'No IT function':0 }[a.i_itFunction] || 0;
  const org = Math.min(10, itPts);

  /* ---- MCP bonus (0–5) ---- */
  let bonus = 0;
  const hasRestGraphql = p==='it' ? (a.c_apiTypes||[]).some(t => t.startsWith('REST') || t === 'GraphQL') : anyRealtime;
  if (hasRestGraphql) bonus += 2;
  if (rtPts >= 5) bonus += 1;                       // real-time flows to build on
  if (mwPts >= 6) bonus += 1;
  if (p==='it' && a.d_gov === 'formal') bonus += 1;
  bonus = Math.min(5, bonus);

  const dims = { integration, data, automation, systems, strategy, org };
  const total = Math.min(100, Math.round(integration + data + automation + systems + strategy + org));
  const t = tierFor(total);

  const maxes = { integration:25, data:20, automation:20, systems:15, strategy:10, org:10 };
  const weakest = Object.keys(dims).sort((x,y) => (dims[x]/maxes[x]) - (dims[y]/maxes[y]))[0];

  /* --- API posture -------------------------------------------------------
     Someone who already exposes APIs does not need a full integration
     platform to connect things — they need a control plane on top of what
     they have. That is a much smaller piece of work, and the report should
     say so rather than pushing middleware at everyone. */
  /* If they explicitly answered "0 active API integrations", that answer wins
     over the API-type checkboxes — naming a protocol is not the same as having
     something running. Without this the report congratulated people who had
     told us they have none. */
  const apiCountZero = a.c_apiCount === '0';
  const declaredApis = (p === 'it' && !apiCountZero)
    ? (a.c_apiTypes || []).filter(t => t !== 'No APIs in use')
    : [];
  const realtimeCount = sys.filter(s => s.connection === 'realtime').length;
  const apiCountHigh = ['6–20','21–50','50+'].includes(a.c_apiCount);
  const apiPosture = (declaredApis.length >= 2 || apiCountHigh || realtimeCount >= 3) ? 'strong'
                   : (declaredApis.length >= 1 || realtimeCount >= 1)                 ? 'partial'
                   : 'none';

  /* --- Security & compliance posture ------------------------------------ */
  const hasMiddlewarePre = toolMw >= 7 || mwPts >= 7;

  /* ---- What architecture do they actually need? -------------------------
     Decided once, here, so the diagram, the benefits, the cost comparison and
     the recommendations can never disagree with each other.

       platform-gateway : they already run a platform → add a gateway on top
       middleware       : heavy landscape, no platform → nervous system first
       gateway          : light landscape, no platform → gateway is enough
  */
  const BIG_CATS = ['erp','crm','ehr','dwh','lake'];
  const bigSystems = [...new Set(sys.filter(x => BIG_CATS.includes(x.cat)).map(x => x.cat))];
  const coreSystems = sys.filter(x => ['erp','ehr','dwh','lake'].includes(x.cat)).length;
  const totalSystems = nonSheet.length;
  const llmNames = [...new Set(sys.filter(x => x.cat === 'ai').map(x => x.name))];
  const hasLlm = llmNames.length > 0;

  const needsMiddleware = bigSystems.length >= 2 || totalSystems > 4;
  const architecture = hasMiddlewarePre ? 'platform-gateway'
                     : needsMiddleware  ? 'middleware'
                     : 'gateway';
  const gatewayOnly = architecture === 'gateway';

  const guardrails = a.au_guardrails || [];
  const hasMiddleware = hasMiddlewarePre;
  const middlewareNames = tools.filter(t => ['enterprise','light','custom'].includes(toolTier(t)));
  const middlewareName = middlewareNames[0] || null;
  const middlewareIsEnterprise = tools.some(t => toolTier(t) === 'enterprise');
  const securityGaps = AI_GUARDRAILS.filter(g => !guardrails.includes(g));
  const securityRisk = (!hasMiddleware || guardrails.length === 0) ? 'high'
                     : securityGaps.length >= 3                   ? 'medium'
                     : 'low';

  return { total, bonus, dimensions: dims, tier: t.key, tierLabel: t.label,
           tierColor: t.color, tierDesc: t.desc, mcpReady: bonus >= 3,
           weakestDimension: weakest, apiPosture, hasMiddleware,
           middlewareName, middlewareIsEnterprise, realtimeCount,
           gatewayOnly, coreSystems, totalSystems, llmNames, hasLlm,
           architecture, bigSystems, needsMiddleware,
           securityRisk, securityGaps, guardrailCount: guardrails.length };
}

/* ------------------------------------------------------------------ */
/*  RECOMMENDATION ENGINE (vendor-neutral)                              */
/* ------------------------------------------------------------------ */

const DIM_LABELS = { integration:'Integration & Connectivity', data:'Data Trust & Governance', automation:'AI & Automation Experience', systems:'System Landscape', strategy:'Strategic Alignment', org:'Organisational Readiness' };

function recommendations(res, a) {
  const p = a.persona, w = res.weakestDimension, recs = [];
  const push = (title, body) => recs.push({ title, body });

  /* Already have APIs? Then the ask is a control plane, not middleware. */
  if (res.apiPosture === 'strong') {
    push('Add an AI Orchestration Layer, not middleware',
      'Your systems already expose APIs, so the connecting work is largely behind you. What is missing is a single control plane above them: one place that decides which agent may call which API, enforces authentication and rate limits, caps AI spend, and logs every call. That is a far smaller project than a full integration programme — you are adding governance, not rebuilding plumbing.');
  }

  /* Ungoverned AI is the most expensive gap to discover late. */
  if (res.securityRisk === 'high') {
    push('Put guardrails around AI before you scale it',
      'Right now there is no single place to control what AI may read, what it may do, or what it costs. Define which data is off limits, mask personal data before it reaches a model, set spend and rate limits, and log every call. Under GDPR and the EU AI Act you need to be able to show all of this — and retrofitting it across a dozen tools costs far more than building it once.');
  }

  if (w === 'integration' && recs.length < 3) {
    if (p==='it') push('Build your API foundation first','Before agents can act on your data, your core systems need exposed APIs. Prioritise API-enabling your CRM and ERP with REST + OAuth 2.0, then adopt an integration platform (iPaaS / middleware) so those APIs are reusable across every future use case — instead of rebuilding point-to-point connections each time.');
    else if (p==='exec') push('Connect your core systems','Your highest-ROI move today is making your CRM, ERP and website share data automatically. Every hour spent copying data between systems is an hour AI cannot reclaim. A connected Integration & Orchestration Layer is the foundation every AI project is built on.');
    else push('Stop copying data by hand','When your CRM, inbox and spreadsheets don\'t talk to each other, your team re-enters data for hours every week — and AI can\'t trust what it reads. Connecting your top 3 tools automatically is your single highest-impact first step.');
  }
  if ((w === 'data' || res.dimensions.data/20 < 0.5) && recs.length < 3) {
    if (p==='it') push('Establish your data-trust layer','AI agents are only as good as the data they act on. Introduce master-data management (MDM) for a single trusted record of customers, products and orders, and profile / clean data before exposing it to any AI system.');
    else push('Clean up your single source of truth','Decide which system holds the "true" version of each record (customer, product, order). Removing duplicates and conflicts now is what lets AI give trustworthy answers later.');
  }
  if (res.dimensions.automation/20 < 0.5 && recs.length < 3) {
    push('Automate one workflow end-to-end','Pick one repetitive, high-volume process and automate it fully before adding AI. It builds the plumbing — and the organisational confidence — that agentic use cases depend on.');
  }
  if (res.tier === 'optimisation' && recs.length < 3) {
    push('Prepare for your first MCP server','You\'re close. Document which data AI is allowed to access and move key flows to real-time, so an API gateway can safely expose them to an LLM orchestrator.');
  }
  if (res.tier === 'agentReady' && recs.length < 3) {
    push('Deploy your first MCP server','Your integration maturity is ready. Expose your top 3 APIs through an MCP server behind an API gateway with rate-limiting, authentication and audit logging, so any LLM can securely query and act on live business data.');
  }
  if (recs.length < 3) push('Define one concrete first use case', p==='ops' ? 'Choose a quick win your team feels daily — e.g. AI that auto-qualifies inbound leads from your CRM — and scope it tightly.' : 'Pick a single, well-bounded use case with clear value and low risk. A focused pilot beats a broad programme for proving value and securing budget.');
  if (recs.length < 3) push('Secure executive sponsorship & budget','Name an owner and ring-fence a first budget. Readiness is as much organisational as technical — a sponsor unblocks the data and integration work agents depend on.');

  return recs.slice(0,3);
}

const TIER_HEADLINE = {
  foundation:'Before AI agents can work for you, your systems need to talk to each other.',
  awareness:'You have the tools — now they need to communicate reliably.',
  integration:'Your foundation is ready — agents can start operating in controlled workflows.',
  optimisation:"You're close to full agent readiness. A few governance and connectivity gaps remain.",
  agentReady:'Your infrastructure is ready for full multi-agent orchestration.',
};

/* ------------------------------------------------------------------ */
/*  RESULT VISUALS                                                      */
/* ------------------------------------------------------------------ */

function Gauge({ value, color, size=220 }) {
  const [disp, setDisp] = useState(0);
  useEffect(() => {
    let raf, start;
    const dur = 1500;
    const tick = (t) => { start = start ?? t; const k = Math.min(1,(t-start)/dur);
      setDisp(Math.round(value*(1-Math.pow(1-k,3)))); if (k<1) raf=requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf);
  }, [value]);
  const r = size/2 - 16, c = 2*Math.PI*r, off = c*(1 - disp/100);
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="#DFD9CC" strokeWidth="16" />
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={color} strokeWidth="16" strokeLinecap="round"
        strokeDasharray={c} strokeDashoffset={off} transform={`rotate(-90 ${size/2} ${size/2})`} />
      <text x="50%" y="47%" textAnchor="middle" fontSize="46" fontWeight="800" fill="#2C3B4D">{disp}<tspan fontSize="22">%</tspan></text>
      <text x="50%" y="63%" textAnchor="middle" fontSize="13" fontWeight="600" fill="#7A7368">Agent Readiness</text>
    </svg>
  );
}

/* Score → colour across the full warm-to-green range, so 1/15 and 10/10 look
   as different as they are. Interpolated rather than banded, which gives every
   intermediate score its own shade. */
const SCORE_STOPS = [
  [0,   [0x8F,0x3D,0x2A]],  // deep rust
  [22,  [0xA3,0x51,0x39]],  // truffle
  [40,  [0xC0,0x66,0x2F]],  // burnt orange
  [55,  [0xB4,0x8A,0x3A]],  // amber-bronze
  [70,  [0x6E,0x81,0x4C]],  // olive
  [85,  [0x3D,0x6B,0x5A]],  // teal
  [100, [0x2E,0x6B,0x45]],  // green
];
function scoreColor(pct) {
  const p = Math.max(0, Math.min(100, pct));
  for (let i = 1; i < SCORE_STOPS.length; i++) {
    const [x1, c1] = SCORE_STOPS[i - 1], [x2, c2] = SCORE_STOPS[i];
    if (p <= x2) {
      const t = (p - x1) / (x2 - x1);
      const ch = c1.map((v, k) => Math.round(v + (c2[k] - v) * t));
      return `rgb(${ch.join(',')})`;
    }
  }
  return `rgb(${SCORE_STOPS[SCORE_STOPS.length - 1][1].join(',')})`;
}

function Bars({ dims }) {
  const maxes = { integration:25, data:20, automation:20, systems:15, strategy:10, org:10 };
  return (
    <div className="space-y-3">
      {Object.keys(dims).map(k => {
        const pct = Math.round(dims[k]/maxes[k]*100);
        const col = scoreColor(pct);
        return (
          <div key={k}>
            <div className="flex justify-between text-sm mb-1">
              <span className="font-medium text-navy">{DIM_LABELS[k]}</span>
              <span className="tabular-nums font-semibold" style={{color:col}}>{Math.round(dims[k])}/{maxes[k]}</span>
            </div>
            <div className="h-2.5 rounded-full bg-slate-200 overflow-hidden">
              <div className="h-full rounded-full transition-all duration-1000" style={{ width:pct+'%', background:col }} />
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* Landscape — every shape is decided by res.architecture, so the picture can
   never contradict the advice.

   Current state   · spaghetti between systems (no AI box at all if they run no
                     LLM today — showing one would be fiction), or routed
                     through the platform they already own.
   Target state    · middleware        → platform at the centre, systems around it
                   · gateway           → gateway directly under the AI
                   · platform-gateway  → their platform, with a gateway on top   */
function Landscape({ mode, nodes, res }) {
  const W = 384, OAT = '#C9C1B1', INK = '#1B2632';
  const before = mode === 'before';
  const arch = res.architecture;
  const hasMw = res.hasMiddleware;
  const short = (t, n = 13) => (t.length > n ? t.slice(0, n - 1) + '…' : t);

  const llm = (res.llmNames || [])[0];
  const aiLabel = llm ? short(llm.replace(/\s*\(.*\)$/, ''), 13) : 'AI / Apps';
  const aiExtra = (res.llmNames || []).length > 1 ? `+${res.llmNames.length - 1} more` : null;
  // No AI today means no AI in the "today" picture.
  const showAi = !before || true;
  const showAiBefore = res.hasLlm;

  const items = nodes.slice(0, 6);
  const radial = !before && (arch === 'middleware' || arch === 'platform-gateway');
  // Where a platform exists, the AI Gateway is a separate tier above it.
  const withGateway = arch === 'platform-gateway';

  /* ---------- radial: the platform as the nervous system ---------- */
  if (radial) {
    const cx = W / 2, cy = withGateway ? 236 : 206, rx = 142, ry = 92;
    /* Systems sit around the platform on an arc that deliberately avoids the
       top, so nothing lands between the AI and the layer it connects to. */
    const n = items.length;
    const [t0, t1] = n >= 5 ? [-40, 220] : [0, 180];
    const ring = items.map((it, i) => {
      const deg = n === 1 ? 90 : t0 + (i * (t1 - t0)) / (n - 1);
      const t = (deg * Math.PI) / 180;
      return { ...it, x: cx + Math.cos(t) * rx, y: cy + Math.sin(t) * ry };
    });
    const H = Math.max(...ring.map(r => r.y)) + 30;
    return (
      <svg viewBox={`0 0 ${W} ${H}`} className="w-full" role="img"
        aria-label="Target state: an integration and orchestration layer at the centre of your systems">
        {ring.map((n, i) => <path key={i} d={`M${cx} ${cy} L${n.x} ${n.y}`} stroke="#2E6B45" strokeWidth="1.8" opacity=".9" />)}
        {withGateway
          ? <>
              <path d={`M${cx} 46 L${cx} 84`} stroke="#2E6B45" strokeWidth="2.6" />
              <path d={`M${cx} 120 L${cx} ${cy - 22}`} stroke="#2E6B45" strokeWidth="2.6" />
            </>
          : <path d={`M${cx} 46 L${cx} ${cy - 22}`} stroke="#2E6B45" strokeWidth="2.6" />}
        {ring.map((n, i) => (
          <g key={i}>
            <rect x={n.x - 44} y={n.y - 11} width="88" height="22" rx="7" fill="#fff"
              stroke={n.api ? '#2E6B45' : OAT} strokeWidth={n.api ? 2 : 1} />
            <text x={n.x - (n.api ? 8 : 0)} y={n.y + 4} textAnchor="middle" fontSize="8.5" fontWeight="600" fill="#2C3B4D">{short(n.label, 11)}</text>
            {n.api && (<g><rect x={n.x + 20} y={n.y - 7} width="22" height="14" rx="7" fill="#2E6B45" />
              <text x={n.x + 31} y={n.y + 3} textAnchor="middle" fontSize="7" fontWeight="800" fill="#fff">API</text></g>)}
          </g>
        ))}
        {/* Integration & Orchestration Layer — the nervous system, at the centre */}
        <g>
          <rect x={cx - 66} y={cy - 22} width="132" height="44" rx="11" fill={INK} />
          {hasMw ? (
            <>
              <text x={cx} y={cy - 4} textAnchor="middle" fontSize="10" fontWeight="800" fill="#FFB162">{short(res.middlewareName || '', 16)}</text>
              <text x={cx} y={cy + 9} textAnchor="middle" fontSize="7.5" fontWeight="700" fill="#FFB162">Integration &amp; Orchestration</text>
            </>
          ) : (
            <>
              <text x={cx} y={cy - 4} textAnchor="middle" fontSize="9.5" fontWeight="800" fill="#FFB162">Integration &amp;</text>
              <text x={cx} y={cy + 9} textAnchor="middle" fontSize="9.5" fontWeight="800" fill="#FFB162">Orchestration Layer</text>
            </>
          )}
        </g>

        {/* AI Gateway — a distinct tier, not folded into the layer below */}
        {withGateway && (
          <g>
            <rect x={cx - 62} y={84} width="124" height="36" rx="10" fill="#3C4E63" />
            <text x={cx} y={101} textAnchor="middle" fontSize="10" fontWeight="800" fill="#FFB162">AI Gateway</text>
            <text x={cx} y={113} textAnchor="middle" fontSize="7.5" fontWeight="600" fill="#DFD9CC">Auth · Limits · Policy · Logs</text>
          </g>
        )}
        <g>
          <rect x={cx - 54} y={16} width="108" height={aiExtra ? 34 : 30} rx="9" fill="#2E6B45" />
          <text x={cx} y={aiExtra ? 31 : 35} textAnchor="middle" fontSize="11" fontWeight="700" fill="#fff">{aiLabel}</text>
          {aiExtra && <text x={cx} y={43} textAnchor="middle" fontSize="7.5" fontWeight="600" fill="#DFD9CC">{aiExtra}</text>}
        </g>
      </svg>
    );
  }

  /* ---------- stacked layouts ---------- */
  const gwTight = !before && arch === 'gateway';
  const hub = { x: W / 2, y: 34 };
  const showLayer = !before || hasMw;
  // With no AI box drawn there is nothing above the layer, so pull it up.
  const layer = { x: W / 2, y: before ? (showAiBefore ? 168 : 74) : (gwTight ? 116 : 168) };
  // With no AI and no platform there is nothing above the systems, so start high.
  const nodeTop = before
    ? (showAiBefore ? 250 : (showLayer ? 156 : 46))
    : (gwTight ? 232 : 286);
  const rows = Math.ceil(Math.min(items.length, 6) / 2);
  const H = nodeTop + rows * 30 + 16;

  const placed = items.map((n, i) => {
    const left = i % 2 === 0, row = Math.floor(i / 2);
    return { ...n, x: left ? 54 : W - 54, y: nodeTop + row * 30 };
  });

  const line = before ? (hasMw ? '#8A6A2E' : '#A35139') : '#2E6B45';
  const layerTitle = before ? short(res.middlewareName || '', 18)
                    : gwTight ? 'AI Gateway'
                    : hasMw   ? short(res.middlewareName || '', 18)
                    : 'AI Gateway Layer';
  const layerSub = before ? null
                  : gwTight ? 'Auth · Limits · Policy · Logging'
                  : hasMw   ? '+ AI Gateway & Orchestration'
                  : 'Integration & Orchestration';

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="w-full" role="img"
      aria-label={before ? 'How your systems connect today' : 'How your systems would connect with a governed layer'}>
      {showLayer ? (
        <g>
          {/* only connect to the AI box when there is one */}
          {(!before || showAiBefore) &&
            <path d={`M${hub.x} ${hub.y + 16} L${layer.x} ${layer.y - 24}`} stroke={line} strokeWidth="2.6" />}
          {placed.map((n, i) => (
            <path key={i} d={`M${n.x} ${n.y} L${layer.x} ${layer.y + 24}`} stroke={line} strokeWidth="1.7" opacity=".9" />
          ))}
        </g>
      ) : (
        placed.map((n, i) => (
          <g key={i}>
            {showAiBefore && <path d={`M${hub.x} ${hub.y + 16} L${n.x} ${n.y}`} stroke={line} strokeWidth="1.3" opacity=".85" />}
            {placed.filter((_, j) => j > i).map((m, j) => (
              <path key={j} d={`M${n.x} ${n.y} L${m.x} ${m.y}`} stroke={line} strokeWidth="1" opacity=".38" strokeDasharray="3 3" />
            ))}
          </g>
        ))
      )}

      {showLayer && (
        <g>
          <rect x={layer.x - 84} y={layer.y - 24} width="168" height={before ? 40 : 46} rx="11"
            fill={before ? '#5C574F' : INK} />
          {before ? (
            <>
              <text x={layer.x} y={layer.y - 6} textAnchor="middle" fontSize="8.5" fontWeight="700" fill={OAT}>YOUR PLATFORM</text>
              <text x={layer.x} y={layer.y + 9} textAnchor="middle" fontSize="11.5" fontWeight="800" fill="#fff">{layerTitle}</text>
            </>
          ) : (
            <>
              <text x={layer.x} y={layer.y - 4} textAnchor="middle" fontSize="11" fontWeight="800" fill="#FFB162">{layerTitle}</text>
              <text x={layer.x} y={layer.y + 11} textAnchor="middle" fontSize="8.5" fontWeight="600" fill="#DFD9CC">{layerSub}</text>
            </>
          )}
        </g>
      )}

      {!before && !gwTight && (
        <g>
          {['Auth', 'Rate limits', 'Policy', 'Token limits'].map((c, i) => {
            const cx = 46 + (i % 2) * 140, cy = layer.y + 46 + Math.floor(i / 2) * 21;
            return (
              <g key={c}>
                <rect x={cx} y={cy - 10} width="128" height="17" rx="8" fill="#EDF3EF" stroke="#BFD3C6" />
                <text x={cx + 64} y={cy + 2} textAnchor="middle" fontSize="8.5" fontWeight="700" fill="#215034">{c}</text>
              </g>
            );
          })}
        </g>
      )}

      {(before ? showAiBefore : true) && (
        <g>
          <rect x={hub.x - 54} y={hub.y - 16} width="108" height={aiExtra ? 34 : 30} rx="9"
            fill={before ? (hasMw ? '#8A6A2E' : '#8F3D2A') : '#2E6B45'} />
          <text x={hub.x} y={aiExtra ? hub.y - 1 : hub.y + 4} textAnchor="middle" fontSize="11" fontWeight="700" fill="#fff">{aiLabel}</text>
          {aiExtra && <text x={hub.x} y={hub.y + 11} textAnchor="middle" fontSize="7.5" fontWeight="600" fill="#DFD9CC">{aiExtra}</text>}
        </g>
      )}

      {placed.map((n, i) => (
        <g key={i}>
          <rect x={n.x - 50} y={n.y - 12} width="100" height="24" rx="7" fill="#fff"
            stroke={n.api ? '#2E6B45' : OAT} strokeWidth={n.api ? 2 : 1} />
          <text x={n.x - (n.api ? 9 : 0)} y={n.y + 4} textAnchor="middle" fontSize="9" fontWeight="600" fill="#2C3B4D">{short(n.label)}</text>
          {n.api && (
            <g>
              <rect x={n.x + 24} y={n.y - 8} width="24" height="16" rx="8" fill="#2E6B45" />
              <text x={n.x + 36} y={n.y + 3.5} textAnchor="middle" fontSize="7.5" fontWeight="800" fill="#fff">API</text>
            </g>
          )}
        </g>
      ))}
    </svg>
  );
}

/* Benefits and cost comparison follow the architecture that was recommended —
   quoting integration-platform ROI at someone who only needs a gateway would be
   dishonest, and vice versa. */
const BENEFITS_MIDDLEWARE = [
  ['70–80%','Fewer integration touchpoints'],
  ['60–70%','Faster onboarding of new systems'],
  ['100%','Consistent security & governance'],
  ['50–60%','API reusability across projects'],
  ['Lower','Total cost of ownership'],
  ['Better','End-to-end visibility & monitoring'],
];
const BENEFITS_GATEWAY = [
  ['100%','AI calls authenticated & scoped'],
  ['Capped','Token spend per team or use case'],
  ['Full','Audit trail of every AI action'],
  ['Any','Model swappable without a rewrite'],
  ['Masked','Personal data before it reaches a model'],
  ['Days','To add a new AI use case safely'],
];

const ARCH_TITLE = {
  'middleware':       'What you need: an integration layer first',
  'gateway':          'What you need: an AI Gateway',
  'platform-gateway': 'What you need: an AI Gateway on the platform you have',
};
const ARCH_SUB = {
  'middleware':       'Your landscape is heavy enough that connecting it properly comes before governing AI.',
  'gateway':          'Your landscape is small enough that the connecting work is not the bottleneck — control is.',
  'platform-gateway': 'The connecting work is done. What is missing is the layer that governs AI on top of it.',
};

const ROI_COLUMNS = {
  middleware: {
    without: ['Many brittle point-to-point integrations','Automated workflows (event triggered) — not available','High development, testing & maintenance cost','Inconsistent security, logging & monitoring','No central control of AI access, cost or compliance','Hard to reuse — every project starts from scratch','Onboarding a new system takes weeks or months'],
    with:    ['One governed layer — update once, not everywhere','Enables automated workflows (event triggered)','Lower cost, less effort, faster delivery','Consistent security, monitoring & governance','Central control of what AI may access and what it costs','APIs reusable across teams and use cases','Onboard new systems in days — and AI can run on top'],
    stats:   [['300%+','Return on investment'],['50–60%','Lower integration effort'],['Days','not months to onboard systems']],
    note:    'Illustrative figures based on typical iPaaS / API-led programmes. Actual numbers vary by organisation and scale.',
  },
  gateway: {
    without: ['Every new AI use case re-solves auth, logging and routing from scratch','Repeated prompts billed again every time — no caching','Every query hits an expensive frontier model, simple or not','Teams buy their own keys and subscriptions — fragmented, duplicated spend','One data-leak incident carries the full cost: fines, notification, reputation','Switching model provider means rewriting the integration'],
    with:    ['New agents inherit auth, logging and routing — weeks saved per use case','Caching removes 20–40% of redundant model calls','Simple queries routed to cheaper models, frontier models kept for hard reasoning','Centralised buying beats fragmented: volume pricing, no forgotten subscriptions','PII redaction at the boundary prevents the incident in the first place','Model swapped by configuration, not by a rewrite'],
    stats:   [['20–40%','Fewer redundant model calls'],['Weeks','Saved per new AI use case'],['1 incident','Avoided pays for the layer']],
    note:    'Caching and routing savings depend on query overlap and traffic mix. The incident comparison is deliberately blunt: weigh one GDPR-level fine against a year of gateway cost.',
  },
};

/* Where it breaks — specific failure points read out of their own answers,
   rather than generic warnings. */
function breakPoints(res, a) {
  const out = [];
  const sys = allSystems(a.systems);
  const disconnected = sys.filter(s => s.connection === 'none' || s.connection === 'manual');
  const lowTrust = sys.filter(s => s.trust <= 2);
  const excel = sys.filter(s => s.cat === 'sheets');

  if (disconnected.length) {
    out.push([`${disconnected.length} system${disconnected.length>1?'s are':' is'} only reachable by hand`,
      `${disconnected.slice(0,3).map(s=>s.name).join(', ')}${disconnected.length>3?' and others':''} ${disconnected.length>1?'are':'is'} not connected automatically. An agent asked "what is the status of this customer?" has no way to read ${disconnected.length>1?'them':'it'} — it will either answer from stale data or make something up.`]);
  }
  if (res.totalSystems > 4 && !res.hasMiddleware) {
    const pairs = (res.totalSystems * (res.totalSystems - 1)) / 2;
    out.push([`${res.totalSystems} systems, no shared connection layer`,
      `Wired directly, ${res.totalSystems} systems can need up to ${pairs} separate connections, and every one of them has to be built, tested and maintained separately. This is the point where teams stop adding integrations because each new one costs too much.`]);
  }
  if (lowTrust.length) {
    out.push([`You do not trust the data in ${lowTrust.map(s=>s.name).slice(0,3).join(', ')}`,
      `You rated ${lowTrust.length>1?'these':'this'} 1–2 out of 5. AI does not hedge: it will state a wrong number with the same confidence as a right one, and your team will find out from the customer.`]);
  }
  if (excel.length) {
    out.push(['Spreadsheets are acting as a system of record',
      `${excel.map(s=>s.name).join(' and ')} cannot be queried reliably by software. Anything that lives only there is invisible to AI, and stays invisible until it moves into a system with an interface.`]);
  }
  if (res.guardrailCount === 0) {
    out.push(['Nothing limits what AI may see, do, or cost',
      'There is no cap on spend, no rule on which data is off limits, and no log of what happened. The first time this matters is usually the first time it goes wrong — an unexpected invoice, or data somewhere it should not be.']);
  }
  if (a.au_live === 'no' || a.au_live === 'none') {
    out.push(['Your AI cannot see your business',
      'Whatever AI you use today works from public information only. It can write text, but it cannot answer a question about your own orders, customers or stock — which is where the value actually is.']);
  }
  if (res.apiPosture === 'none' && !res.hasMiddleware) {
    out.push(['No programmatic way in',
      'None of your systems currently expose an interface software can call. Until at least your two most important ones do, an agent has nothing to act on, however capable the model is.']);
  }
  return out.slice(0, 5);
}

/* ------------------------------------------------------------------ */
/*  STEP COMPONENTS                                                     */
/* ------------------------------------------------------------------ */

function Progress({ step, onJump, maxStep, statusOf }) {
  return (
    <nav className="mb-8" aria-label="Assessment progress">
      <div className="flex items-start justify-between gap-1">
        {STEPS.map((s,i) => {
          const status = statusOf ? statusOf(i) : (i < step ? 'done' : 'todo');
          const now = i === step;
          const touched = status !== 'todo';
          // Anything already visited stays open, in both directions.
          const reachable = i !== step && (i + 1) <= maxStep;
          const partial = status === 'partial' && !now;
          const tint = touched || now ? s.color : '#DDD8CC';
          return (
            <div key={s.label} className="flex-1 flex flex-col items-center gap-1.5">
              <button
                type="button"
                onClick={() => reachable && onJump && onJump(i)}
                disabled={!reachable}
                title={reachable ? `Go to ${s.label}` : s.label}
                aria-current={now ? 'step' : undefined}
                className={`flex h-8 w-8 items-center justify-center rounded-full transition ${reachable ? 'cursor-pointer hover:scale-110' : 'cursor-default'}`}
                style={{
                  // In-progress keeps the stage colour but stays hollow, so a
                  // half-finished stage never reads as finished.
                  background: partial ? '#fff' : (touched || now ? s.color : '#EDEAE3'),
                  boxShadow: now ? `0 0 0 3px ${s.color}33` : (partial ? `inset 0 0 0 2px ${s.color}` : 'none'),
                }}>
                <Icon name={s.icon} size={16} color={partial ? s.color : (touched || now ? '#fff' : '#9A9285')} strokeWidth={2} />
              </button>
              <div className="h-1.5 w-full rounded-full transition-all"
                style={{ background: tint, opacity: partial ? 0.4 : now ? 0.55 : 1 }} />
              <span className="hidden sm:block text-[10px] font-medium leading-tight text-center"
                style={{ color: now ? s.color : touched ? '#5C574F' : '#9A9285', fontWeight: now ? 700 : 500 }}>
                {s.label}{partial && <span style={{color:s.color}}> ·</span>}
              </span>
            </div>
          );
        })}
      </div>
      <div className="sm:hidden mt-2 text-center text-xs font-bold" style={{ color: STEPS[step]?.color }}>
        Step {step+1} of {STEPS.length} · {STEPS[step]?.label}
      </div>
    </nav>
  );
}

/* ------------------------------------------------------------------ */
/*  INTRO / LANDING — the front door of the site                        */
/* ------------------------------------------------------------------ */

/* Flat editorial illustration: growth, measurement, people moving it along.
   Hand-authored so it ships inside the single-file build with no asset
   requests, and so it uses the brand palette exactly. */
function HeroArt() {
  const CREAM = '#EEE9DF', FLAME = '#FFB162', INK = '#1B2632', OAT = '#C9C1B1', RUST = '#A35139';
  const bars = [
    { x: 196, top: 214 },
    { x: 289, top: 158 },
    { x: 382, top: 104 },
  ];
  const Person = ({ x, shirt, flip }) => (
    <g transform={`translate(${x},0) scale(${flip ? -1 : 1},1)`}>
      {/* legs */}
      <path d="M0 262 L-11 320" stroke={INK} strokeWidth="12" strokeLinecap="round" fill="none" />
      <path d="M0 262 L13 318" stroke="#3C4E63" strokeWidth="12" strokeLinecap="round" fill="none" />
      {/* torso */}
      <path d="M0 218 L0 264" stroke={shirt} strokeWidth="27" strokeLinecap="round" fill="none" />
      {/* arm reaching toward the bar */}
      <path d="M9 228 L52 243" stroke={shirt} strokeWidth="10" strokeLinecap="round" fill="none" />
      <circle cx="55" cy="244" r="6" fill={CREAM} />
      {/* head */}
      <circle cx="0" cy="196" r="15" fill={CREAM} />
      <path d="M-15 192a15 15 0 0 1 30 0q-8-7-15-3-7 4-15 3z" fill={INK} />
    </g>
  );
  return (
    <svg viewBox="0 0 640 400" className="w-full h-auto" role="img"
      aria-label="Illustration: two people moving rising chart bars upward, with a pie chart above">
      <defs>
        <pattern id="hero-dots" width="9" height="9" patternUnits="userSpaceOnUse">
          <circle cx="2" cy="2" r="1.25" fill={OAT} opacity="0.85" />
        </pattern>
      </defs>

      <rect width="640" height="400" rx="24" fill="#2C3B4D" />

      {/* pie chart */}
      <g transform="translate(252,92)">
        <circle r="60" fill={CREAM} stroke={INK} strokeWidth="3" />
        <path d="M0 0 L0 -60 A60 60 0 0 0 -52 -30 Z" fill="#3C4E63" />
        <path d="M0 0 L-52 -30 A60 60 0 0 0 -30 52 Z" fill={OAT} />
        <path d="M0 0 L-30 52 A60 60 0 0 0 42 43 Z" fill={FLAME} />
        <circle r="60" fill="none" stroke={INK} strokeWidth="3" />
      </g>

      {/* ground */}
      <path d="M96 331 H556" stroke={INK} strokeWidth="3" strokeLinecap="round" opacity=".5" />

      {/* bars */}
      {bars.map((b, i) => (
        <g key={i}>
          <rect x={b.x} y={b.top} width="80" height={331 - b.top} rx="4" fill={CREAM} />
          <rect x={b.x} y={b.top} width="80" height={331 - b.top} rx="4" fill="url(#hero-dots)" />
          <rect x={b.x} y={b.top} width="80" height="12" rx="3" fill={CREAM} stroke={INK} strokeWidth="2.5" />
          <rect x={b.x} y={b.top} width="80" height={331 - b.top} rx="4" fill="none" stroke={INK} strokeWidth="2.5" />
        </g>
      ))}

      {/* growth line */}
      <path d="M150 306 L232 232 L268 262 L322 196 L366 226 L420 152 L456 178 L520 112"
        fill="none" stroke={INK} strokeWidth="4" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M498 106 L524 108 L522 134" fill="none" stroke={INK} strokeWidth="4"
        strokeLinecap="round" strokeLinejoin="round" />

      {/* plants */}
      {[168, 476].map((px, i) => (
        <g key={i} transform={`translate(${px},331)`}>
          <path d="M0 0 C2 -22 6 -34 10 -44" stroke={FLAME} strokeWidth="3" fill="none" strokeLinecap="round" />
          <ellipse cx="3" cy="-16" rx="7" ry="4" fill={FLAME} transform="rotate(-28 3 -16)" />
          <ellipse cx="10" cy="-30" rx="7" ry="4" fill={FLAME} transform="rotate(-40 10 -30)" />
          <ellipse cx="-4" cy="-26" rx="6" ry="3.5" fill={RUST} transform="rotate(28 -4 -26)" />
        </g>
      ))}

      {/* speech bubble */}
      <g transform="translate(128,150)">
        <rect width="62" height="36" rx="10" fill="#3C4E63" />
        <path d="M18 36 L18 47 L30 36 Z" fill="#3C4E63" />
        <circle cx="18" cy="18" r="4" fill={OAT} />
        <circle cx="31" cy="18" r="4" fill={FLAME} />
        <circle cx="44" cy="18" r="4" fill={OAT} />
      </g>

      <Person x={128} shirt={FLAME} />
      <Person x={512} shirt="#3C4E63" flip />
    </svg>
  );
}

/* Uses your own artwork when public/<heroImage> exists, and falls back to the
   built-in illustration if it does not — so dropping the file in is the only
   step needed, with no code change. */
function Hero() {
  const [failed, setFailed] = useState(false);
  if (!CONFIG.heroImage || failed) return <HeroArt />;
  return (
    <img src={CONFIG.heroImage} onError={() => setFailed(true)}
      alt="Illustration: people moving rising chart bars upward, with a pie chart above"
      className="w-full h-auto rounded-3xl" />
  );
}

/* The six scored dimensions, described for a non-technical reader. */
const WHAT_WE_MEASURE = [
  { icon:'link',     name:'Integration & Connectivity', pts:25, desc:'Do your systems talk to each other — automatically, or by copy-paste? The single biggest predictor of whether AI will work for you.' },
  { icon:'database', name:'Data Trust & Governance',    pts:20, desc:'Is your data clean and consistent enough for AI to act on it? An AI reading bad data gives confident wrong answers.' },
  { icon:'zap',      name:'AI & Automation Experience', pts:20, desc:'What is already automated, and how far AI has got in your business so far. Existing automation is the runway.' },
  { icon:'grid',     name:'System Landscape',           pts:15, desc:'How many systems you run and how joined-up they are. More silos means more places for the truth to disagree with itself.' },
  { icon:'target',   name:'Strategic Alignment',        pts:10, desc:'A clear goal, a realistic timeline and budget behind it. Projects without an owner stall regardless of the technology.' },
  { icon:'user',     name:'Organisational Readiness',   pts:10, desc:'The people and IT capability to deliver and maintain it, whether that is an internal team or a partner.' },
];

const HOW_IT_WORKS = [
  ['target', 'Answer',  'Your role, your systems, and how they connect. Everything starts at "none" — there are no wrong answers.'],
  ['award',  'Score',   'A readiness score out of 100, worked out instantly in your browser.'],
  ['zap',    'Act',     'A prioritised roadmap you can export as a PDF and share with your team.'],
];

/* The full overview, rendered inside the app so it works on any host and in
   any preview — a separate HTML file 404s wherever only index.html is served. */
function About({ onBack, onStart }) {
  const Row = ({ icon, title, children }) => (
    <div className="flex gap-3">
      <span className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-amber-100">
        <Icon name={icon} size={16} color="#A35139" strokeWidth={2} />
      </span>
      <div><p className="font-bold text-navy">{title}</p><p className="text-sm text-slate-600 mt-0.5">{children}</p></div>
    </div>
  );
  return (
    <div className="step-anim mx-auto max-w-2xl">
      <header>
        <div className="inline-flex items-center gap-2 rounded-full bg-navy px-4 py-1.5 text-xs font-semibold tracking-wide text-amber-400">
          <Icon name="compass" size={14} color="#FFB162" /> ABOUT THE COMPASS
        </div>
        <h1 className="mt-5 text-3xl sm:text-4xl font-extrabold tracking-tight text-navy leading-tight" style={{textWrap:'balance'}}>
          What is the <span className="text-amber-600">AI Readiness Compass</span>?
        </h1>
        <p className="mt-4 text-lg text-slate-600">
          A free, 6-minute self-assessment that tells you whether your company's systems and data can
          actually support AI that does real work — and exactly what to fix first.
        </p>
      </header>

      <section className="mt-10">
        <h2 className="text-xl font-bold text-navy">The problem it solves</h2>
        <p className="mt-3 text-slate-600">
          Most AI projects don't fail because the model isn't clever enough. They fail because the
          systems underneath can't give the AI anything trustworthy to work with.
        </p>
        <p className="mt-3 text-slate-600">
          Useful AI isn't a chatbot writing marketing copy. It's an assistant that can answer
          <i> "where is order 4471?"</i>, update a customer record, flag an invoice, or brief your team
          on an account. Every one of those needs the AI to read the truth out of your systems and,
          sometimes, act on it safely.
        </p>
        <div className="mt-4 border-l-4 border-amber-500 pl-4 text-navy">
          If your CRM, your ERP and your spreadsheets only exchange information because a person
          copies it between them, an AI agent has nothing solid to stand on.
        </div>
      </section>

      <section className="mt-10">
        <h2 className="text-xl font-bold text-navy">What it measures</h2>
        <p className="mt-1 mb-4 text-sm text-slate-500">Six weighted dimensions, 100 points in total.</p>
        <div className="grid sm:grid-cols-2 gap-3">
          {WHAT_WE_MEASURE.map(d => (
            <div key={d.name} className="rounded-xl border border-slate-200 bg-white p-4">
              <div className="flex items-center justify-between gap-2">
                <span className="flex items-center gap-2 font-semibold text-navy">
                  <span className="flex h-7 w-7 items-center justify-center rounded-lg bg-amber-100">
                    <Icon name={d.icon} size={15} color="#A35139" strokeWidth={2} />
                  </span>{d.name}
                </span>
                <span className="shrink-0 text-xs font-bold tabular-nums text-amber-600">{d.pts} pts</span>
              </div>
              <p className="mt-2 text-sm text-slate-600">{d.desc}</p>
            </div>
          ))}
        </div>
        <p className="mt-3 text-sm text-slate-500">
          There is also a small bonus score for <b>MCP readiness</b> — whether your systems could
          safely be opened to an AI assistant through one secure, controlled doorway.
        </p>
      </section>

      <section className="mt-10">
        <h2 className="text-xl font-bold text-navy">Your result</h2>
        <p className="mt-3 text-slate-600">Your total puts you in one of five stages, each with a different first move.</p>
        <div className="mt-3 space-y-2">
          {TIERS.map(t => (
            <div key={t.key} className="flex items-center gap-3 rounded-xl border border-slate-200 bg-white p-3">
              <span className="shrink-0 rounded-full px-2.5 py-1 text-[11px] font-bold text-white tabular-nums" style={{background:t.color}}>
                {t.min}–{t.max}%
              </span>
              <div><span className="font-bold text-navy">{t.label}</span>
                <span className="text-sm text-slate-600"> — {t.desc}</span></div>
            </div>
          ))}
        </div>
      </section>

      <section className="mt-10">
        <h2 className="text-xl font-bold text-navy">What you'll get</h2>
        <div className="mt-4 space-y-4">
          <Row icon="award" title="A score you can act on">Your readiness percentage and stage, plus a breakdown across all six dimensions so you can see what is actually holding you back.</Row>
          <Row icon="zap" title="Where it breaks — specifically">Read from your own answers: which systems are only reachable by hand, how many connections an unmanaged landscape would need, which data you told us you don't trust.</Row>
          <Row icon="link" title="Your landscape today vs. the target">Two pictures side by side: how your systems connect now, and the architecture your particular landscape calls for.</Row>
          <Row icon="target" title="Three prioritised next steps">Written for your role — not a generic checklist — plus a cost comparison for the change being recommended.</Row>
          <Row icon="database" title="A PDF you can keep">Export the whole report and share it with your team or your IT partner.</Row>
        </div>
      </section>

      <section className="mt-10">
        <h2 className="text-xl font-bold text-navy">The two layers it talks about</h2>
        <p className="mt-3 text-slate-600">
          Almost every recommendation points at one of two things. They are different jobs, and the
          assessment works out which one you actually need.
        </p>
        <div className="mt-4 grid sm:grid-cols-2 gap-3">
          <div className="rounded-xl border border-slate-200 bg-white p-4">
            <p className="font-bold text-navy">Integration &amp; Orchestration Layer</p>
            <p className="mt-1 text-sm text-slate-600">
              The <b>nervous system</b>. Sits at the centre of your systems and connects each one once,
              in a reusable, governed way — so a change means updating one place, not ten. Recommended
              when you run several core systems (ERP, CRM, warehouse) with nothing joining them up.
            </p>
          </div>
          <div className="rounded-xl border border-slate-200 bg-white p-4">
            <p className="font-bold text-navy">AI Gateway</p>
            <p className="mt-1 text-sm text-slate-600">
              The <b>control point</b> every AI request passes through: who may call what, spend limits,
              policy, data masking and a full audit trail. Recommended when your landscape is small,
              or added on top when you already run an integration platform.
            </p>
          </div>
        </div>
        <p className="mt-3 text-sm text-slate-500">
          If you already run something like n8n, Zapier or MuleSoft, the report will not sell you a
          second platform — it tells you to keep what you have and add governance on top.
        </p>
      </section>

      <section className="mt-10">
        <h2 className="text-xl font-bold text-navy">Who it's for</h2>
        <p className="mt-3 text-slate-600">
          Pick your role at the start and the questions, the wording and the recommendations all change:
        </p>
        <ul className="mt-3 space-y-2">
          {[['Business owners and leadership','Strategic language, cost and ROI, a roadmap you can act on.'],
            ['Sales, marketing and operations','Your day-to-day tools and manual handoffs, in plain language, with no technical knowledge assumed.'],
            ['IT managers and architects','Full technical depth on APIs, integration and data governance.']].map(([t,d])=>(
            <li key={t} className="flex gap-2 text-slate-600">
              <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-amber-500" />
              <span><b className="text-navy">{t}</b> — {d}</span>
            </li>
          ))}
        </ul>
        <p className="mt-3 text-slate-600">
          Built for small and mid-sized companies. Nothing to prepare, and you don't need to know
          what's under the bonnet — <b>"I'm not sure" is a valid answer throughout</b>, and every
          question starts at "none".
        </p>
      </section>

      <section className="mt-10 grid sm:grid-cols-2 gap-3">
        <div className="rounded-2xl border-2 border-green-200 bg-green-50/50 p-5">
          <p className="flex items-center gap-2 font-bold text-green-800"><Icon name="shield" size={17} color="#2E6B45" /> Nothing is collected</p>
          <p className="mt-1.5 text-sm text-slate-600">
            The whole assessment runs in your browser. No sign-up, no form, no database, no cookies,
            no tracking. Your answers vanish when you close the tab unless you export the PDF yourself.
          </p>
        </div>
        <div className="rounded-2xl border-2 border-amber-200 bg-amber-50/60 p-5">
          <p className="flex items-center gap-2 font-bold text-amber-700"><Icon name="compass" size={17} color="#A35139" /> Vendor-neutral</p>
          <p className="mt-1.5 text-sm text-slate-600">
            No product is named or sold. Recommendations point to the <i>kind</i> of capability you
            need, never a specific vendor — the point is an honest picture, not a sales pitch.
          </p>
        </div>
      </section>

      <section className="mt-10 rounded-3xl bg-navy p-8 text-center text-white">
        <h2 className="text-2xl font-bold">Ready to find out where you stand?</h2>
        <p className="mx-auto mt-2 max-w-md text-slate-200">Six minutes, no signup, and an honest answer at the end.</p>
        <div className="mt-6 flex flex-wrap justify-center gap-3">
          <Btn onClick={onStart} className="px-8 py-3.5 text-base">Start the free assessment →</Btn>
          <Btn variant="ghost" className="!text-white !border-white/40 hover:!border-white" onClick={onBack}>← Back</Btn>
        </div>
      </section>
    </div>
  );
}

function Welcome({ onStart, onAbout }) {
  return (
    <div className="step-anim mx-auto max-w-2xl">

      {/* ---- Hero ---- */}
      <header className="text-center pt-2">
        <div className="inline-flex items-center gap-2 rounded-full bg-navy px-4 py-1.5 text-xs font-semibold tracking-wide text-amber-400">
          <Icon name="compass" size={14} color="#FFB162" /> FREE SELF-ASSESSMENT
        </div>
        <h1 className="mt-6 text-4xl sm:text-5xl font-extrabold tracking-tight text-navy leading-[1.08]" style={{textWrap:'balance'}}>
          AI Readiness<br /><span className="text-amber-600">Compass</span>
        </h1>
        <p className="mt-5 text-lg text-slate-600" style={{textWrap:'balance'}}>
          Find out whether your business is really ready for AI — and what to fix first.
        </p>
      </header>

      {/* ---- The centrepiece ---- */}
      <div className="mt-8"><Hero /></div>

      {/* ---- Primary CTA ---- */}
      <div className="mt-8 text-center">
        <Btn onClick={onStart} className="px-8 py-3.5 text-base">Start the free assessment →</Btn>
        <div className="mt-3 flex flex-wrap items-center justify-center gap-x-4 gap-y-1 text-xs text-slate-400">
          <span className="inline-flex items-center gap-1.5"><Icon name="compass" size={13} color="#9A9285" /> 6 minutes</span>
          <span className="inline-flex items-center gap-1.5"><Icon name="user" size={13} color="#9A9285" /> No signup</span>
          <span className="inline-flex items-center gap-1.5"><Icon name="shield" size={13} color="#9A9285" /> Nothing is stored</span>
        </div>
      </div>

      {/* ---- What it is, in short ---- */}
      <section className="mt-12">
        <h2 className="text-xl font-bold text-navy">Why this exists</h2>
        <p className="mt-3 text-slate-600">
          Every business is being told to "do something with AI". The hard part is knowing whether
          your foundations can carry it. AI that actually does work — checking an order, updating a
          record, answering a customer properly — has to read the truth out of your systems and act
          on it safely.
        </p>
        <p className="mt-3 text-slate-600">
          If your CRM, your ERP and your spreadsheets only talk to each other through people, no
          amount of AI will fix that. This assessment scores that foundation, shows you where the
          gaps are, and tells you what to do first — <strong className="text-navy">without selling
          you any particular software</strong>.
        </p>
        <div className="mt-5">
          <button onClick={onAbout}
            className="inline-flex items-center gap-2 rounded-xl border-2 border-navy px-5 py-2.5 font-semibold text-navy transition hover:bg-navy hover:text-cream">
            <Icon name="compass" size={17} /> What is it? Read the full overview →
          </button>
        </div>
      </section>

      {/* ---- How it works ---- */}
      <section className="mt-12">
        <h2 className="text-xl font-bold text-navy">How it works</h2>
        <ol className="mt-4 grid sm:grid-cols-3 gap-3">
          {HOW_IT_WORKS.map(([ic, title, desc], i) => (
            <li key={title} className="rounded-2xl border border-slate-200 bg-white p-5">
              <span className="flex h-9 w-9 items-center justify-center rounded-xl bg-amber-100">
                <Icon name={ic} size={17} color="#A35139" strokeWidth={2} />
              </span>
              <p className="mt-3 text-xs font-bold tabular-nums tracking-wide text-amber-600">STEP {i + 1}</p>
              <p className="font-bold text-navy">{title}</p>
              <p className="mt-1 text-sm text-slate-600">{desc}</p>
            </li>
          ))}
        </ol>
      </section>

      {/* ---- Trust line ---- */}
      <p className="mt-6 flex items-start justify-center gap-2 text-center text-sm text-slate-500">
        <Icon name="shield" size={16} color="#2E6B45" className="mt-0.5 shrink-0" />
        <span>Your answers never leave your browser. No sign-up, no database, no cookies, no tracking.</span>
      </p>

      {/* ---- Closing CTA ---- */}
      <section className="mt-10 rounded-3xl bg-navy p-8 text-center text-white">
        <h2 className="text-2xl font-bold">Ready to find out where you stand?</h2>
        <p className="mx-auto mt-2 max-w-md text-slate-200">
          Six minutes now can save months of building AI on foundations that cannot carry it.
        </p>
        <div className="mt-6"><Btn onClick={onStart} className="px-8 py-3.5 text-base">Start the free assessment →</Btn></div>
        <p className="mt-6 text-sm text-slate-200">
          Questions, or want to talk it through?{' '}
          <a href={`mailto:${CONFIG.contactEmail}`} className="font-semibold text-amber-400 underline">
            {CONFIG.contactEmail}
          </a>
        </p>
      </section>
    </div>
  );
}

function StepCompany({ a, set }) {
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">Tell us about your company</h2>
      <p className="text-slate-500 mb-6">This tailors the questions and your result. Nothing you enter is sent anywhere.</p>
      <Field label="Company name (optional — only used to label your report)">
        <input className={inputCls} value={a.i_company||''} onChange={e=>set({i_company:e.target.value})} placeholder="e.g. Muster GmbH" />
      </Field>
      <Field label="Industry" missing={!a.i_industry}><select className={inputCls} value={a.i_industry||''} onChange={e=>set({i_industry:e.target.value})}><option value="" disabled>Select…</option>{INDUSTRIES.map(x=><option key={x}>{x}</option>)}</select></Field>
      <Field label="Company size" missing={!a.i_size}><Radio options={COMPANY_SIZES} value={a.i_size} onChange={v=>set({i_size:v})} cols={2} /></Field>
      <Field label="IT function" missing={!a.i_itFunction}><Radio options={IT_FUNCTIONS} value={a.i_itFunction} onChange={v=>set({i_itFunction:v})} cols={2} /></Field>
    </div>
  );
}

function StepPersona({ a, set }) {
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">What best describes your role?</h2>
      <p className="text-slate-500 mb-6">We adapt the questions, language and recommendations to match.</p>
      <div className="space-y-3">
        {Object.values(PERSONAS).map(pn => {
          const on = a.persona === pn.key;
          return (
            <button key={pn.key} onClick={()=>set(pn.key === 'it'
                ? { persona: pn.key }
                : { persona: pn.key,
                    au_noGuardrails: a.au_guardrails?.length ? false : true })}
              className={`flex w-full items-start gap-4 rounded-2xl border-2 p-5 text-left transition ${on?'border-amber-500 bg-amber-50':'border-slate-200 bg-white hover:border-slate-300'}`}>
              <div className={`flex h-12 w-12 shrink-0 items-center justify-center rounded-xl ${on?'bg-amber-500 text-navy':'bg-navy text-amber-400'}`}><Icon name={pn.icon} /></div>
              <div>
                <div className="font-bold text-navy">{pn.title}</div>
                <div className="text-xs text-slate-500 mt-0.5">{pn.roles}</div>
                <div className="text-sm text-slate-600 mt-1.5">{pn.blurb}</div>
              </div>
            </button>
          );
        })}
      </div>
    </div>
  );
}

function OtherField({ value, onChange, placeholder='Other (please specify)' }) {
  return <input className={inputCls + ' mt-2'} value={value||''} onChange={e=>onChange(e.target.value)} placeholder={placeholder} />;
}

function StepVision({ a, set, tip }) {
  const goalLabel = g => a.persona==='it' ? g.it : g.biz;
  const toggle = (key, val) => { const cur=a[key]||[]; set({[key]: cur.includes(val)?cur.filter(x=>x!==val):[...cur,val]}); };
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">Your AI vision & ambition</h2>
      <p className="text-slate-500 mb-6">{a.persona==='exec'?'Where do you want AI to move the business?':a.persona==='ops'?'What would make your daily work easier?':'What outcomes are you targeting?'}</p>

      <Field label="What do you primarily want to achieve with AI? (select all that apply)" missing={!(a.v_goals||[]).length}>
        <p className="-mt-1 mb-2 text-xs text-slate-400">Listed from the most focused scope to the broadest.</p>
        <div className="grid gap-2">
          {AI_GOALS.map(g => { const on=(a.v_goals||[]).includes(g.id);
            return (
              <Choice key={g.id} selected={on} onClick={()=>toggle('v_goals',g.id)}>
                <div className="flex items-center justify-between gap-3">
                  <span className={`text-sm ${on?'font-semibold text-navy':'text-slate-700'}`}>{goalLabel(g)}</span>
                  <span className="shrink-0 rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-slate-500">{g.scope}</span>
                </div>
              </Choice>
            ); })}
        </div>
        <OtherField value={a.v_goalOther} onChange={v=>set({v_goalOther:v})} placeholder="Other goal (optional)" />
      </Field>

      <Field label="How far do you want to take AI? (select one)" missing={a.v_ambition===undefined}>
        <div className="grid gap-2">
          {AMBITION.map(m => { const on=a.v_ambition===m.lvl;
            return (
              <button key={m.lvl} onClick={()=>set({v_ambition:m.lvl})}
                className={`text-left rounded-xl border-2 px-4 py-3 transition ${on?'border-amber-500 bg-amber-50':'border-slate-200 bg-white hover:border-slate-300'}`}>
                <div className="text-sm font-bold text-navy">{m.name}</div>
                <div className="text-xs text-slate-500 mt-0.5">{m.desc}</div>
              </button>
            ); })}
        </div>
      </Field>

      <Field label="Who should this AI serve? (optional)">
        <MultiCheck options={['Customer-facing (External)','Employee-facing (Internal)','Both — whole-landscape 360° (Internal & External)']} values={a.v_facing||[]} onToggle={v=>toggle('v_facing',v)} cols={2} />
      </Field>

      <Field label="Timeline expectation" missing={!a.v_timeline}><Radio options={TIMELINES} value={a.v_timeline} onChange={v=>set({v_timeline:v})} /></Field>
      <Field label="Estimated budget for AI / integration investment" missing={!a.v_budget}>
        <Radio options={BUDGETS} value={a.v_budget} onChange={v=>set({v_budget:v})} cols={2} />
      </Field>
    </div>
  );
}

function SystemCategory({ cat, state, update, tip }) {
  const [open, setOpen] = useState(false);
  const s = state || { notInUse: true, items: {} };
  const items = s.items || {};
  const count = Object.keys(items).length;
  const setNotInUse = () => update({ notInUse: true, items: {} });
  const addTool = (name) => { if (!name) return; const it={...items}; if(it[name]){delete it[name];} else {it[name]={trust:3,connection:'none'};} update({ notInUse:false, items: it }); };
  const setItem = (name, patch) => update({ notInUse:false, items: { ...items, [name]: { ...items[name], ...patch } } });
  return (
    <div className={`rounded-xl border bg-white overflow-hidden ${cat.highlight?'border-amber-400 ring-1 ring-amber-200':'border-slate-200'}`}>
      <button onClick={()=>setOpen(o=>!o)} className="flex w-full items-center justify-between px-4 py-3 text-left">
        <span className="flex items-center gap-2 font-semibold text-navy">
          {cat.highlight && <Icon name="zap" size={15} color="#A35139" strokeWidth={2.2} />}
          {cat.name}
        </span>
        <span className="flex items-center gap-2">
          {count>0 && <span className="rounded-full bg-amber-500 px-2 py-0.5 text-xs font-bold text-navy">{count}</span>}
          {count===0 && s.notInUse && <span className="text-xs text-slate-400">None</span>}
          <svg width="16" height="16" viewBox="0 0 24 24" className={`transition ${open?'rotate-180':''}`} fill="none" stroke="#7A7368" strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>
        </span>
      </button>
      {open && (
        <div className="border-t border-slate-100 px-4 py-3 space-y-3">
          {cat.hint && <p className="text-xs text-slate-500">{cat.hint}</p>}
          <label className="flex items-center gap-2 text-sm text-slate-600">
            <input type="checkbox" checked={!!s.notInUse && count===0} onChange={setNotInUse} className="accent-amber-500" /> None / Not in use
          </label>
          {cat.tools.length>0 && (
            <div className="flex flex-wrap gap-2">
              {cat.tools.map(t => { const on=!!items[t];
                return <button key={t} onClick={()=>addTool(t)} className={`rounded-full border px-3 py-1 text-xs font-medium transition ${on?'border-amber-500 bg-amber-500 text-navy':'border-slate-300 bg-white text-slate-600 hover:border-slate-400'}`}>{t}</button>; })}
            </div>
          )}
          <AddCustom onAdd={addTool} />
          {Object.entries(items).map(([name,v]) => (
            <div key={name} className="rounded-lg bg-cream/70 border border-slate-100 p-3">
              <div className="flex items-center justify-between">
                <span className="text-sm font-semibold text-navy">{name}</span>
                <button onClick={()=>addTool(name)} className="text-xs text-slate-400 hover:text-red-600">remove</button>
              </div>
              <div className="mt-2">
                <div className="flex justify-between text-xs text-slate-500 mb-1"><span>Data trust</span><span>{['','Unreliable','Weak','Acceptable','Good','Fully trusted'][v.trust]}</span></div>
                <input type="range" min="1" max="5" value={v.trust} onChange={e=>setItem(name,{trust:+e.target.value})} className="w-full" />
              </div>
              <div className="mt-2">
                <div className="text-xs text-slate-500 mb-1">How is it <Tip term="integration layer" show={tip}>connected</Tip>?</div>
                <div className="flex flex-wrap gap-1.5">
                  {CONNECTIONS.map(c => (
                    <button key={c.key} onClick={()=>setItem(name,{connection:c.key})}
                      className={`rounded-md px-2 py-1 text-[11px] font-medium border transition ${v.connection===c.key?'text-white border-transparent':'bg-white text-slate-600 border-slate-200'}`}
                      style={v.connection===c.key?{background:c.color}:{}}>{c.label}</button>
                  ))}
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function AddCustom({ onAdd }) {
  const [v,setV] = useState('');
  return (
    <div className="flex gap-2">
      <input className={inputCls+' py-2 text-sm'} value={v} onChange={e=>setV(e.target.value)} placeholder="Add custom / other tool…" onKeyDown={e=>{if(e.key==='Enter'&&v.trim()){onAdd(v.trim());setV('');}}} />
      <Btn variant="ghost" className="px-3 py-2 text-sm" onClick={()=>{if(v.trim()){onAdd(v.trim());setV('');}}}>Add</Btn>
    </div>
  );
}

function StepSystems({ a, set, tip }) {
  const cats = CATEGORIES.filter(c => !c.industry || c.industry === a.i_industry);
  const update = (key, val) => set({ systems: { ...a.systems, [key]: val } });
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">Which systems do you use?</h2>
      <p className="text-slate-500 mb-6">Expand a category, pick your tools (or add your own), and rate each one. Everything defaults to <b>None</b>.</p>
      <div className="space-y-2.5">
        {cats.map((c,i) => (
          <React.Fragment key={c.key}>
            {c.group !== (cats[i-1] && cats[i-1].group) && (
              <div className="flex items-center gap-2 pt-3 first:pt-0">
                <span className="text-[11px] font-bold uppercase tracking-wider text-slate-400">{c.group}</span>
                <span className="h-px flex-1 bg-slate-200" />
              </div>
            )}
            <SystemCategory cat={c} state={a.systems[c.key]} update={v=>update(c.key,v)} tip={tip} />
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

function StepConnectivity({ a, set, tip }) {
  const p = a.persona;
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">How are your systems connected?</h2>
      <p className="text-slate-500 mb-6">The heart of agent readiness: can data move safely and automatically?</p>

      {/* Asked of everyone — a middleware platform is the strongest single
          signal of readiness, and it was previously invisible for two of the
          three roles. */}
      <Field label="Which automation or integration tools do you use?" missing={a.c_hasTools==='Yes — we use one or more' ? !(a.c_tools||[]).length : !a.c_hasTools}>
        <p className="-mt-1 mb-2 text-xs text-slate-400">Platforms that move data between your systems automatically — for example Zapier, Make, n8n, Power Automate or a larger integration platform.</p>
        <Radio
          options={['None — we don\'t use one','Yes — we use one or more','I don\'t know']}
          value={a.c_hasTools}
          onChange={v=>set({ c_hasTools:v, c_tools: v==='Yes — we use one or more' ? (a.c_tools||[]) : [] })} />
        {/* Same control for every role — a company can genuinely run more than one. */}
        {a.c_hasTools === 'Yes — we use one or more' && (
          <div className="mt-3">
            <p className="mb-2 text-xs text-slate-400">Select every one you use.</p>
            <MultiCheck options={AUTOMATION_TOOLS.map(t=>t.name)} values={a.c_tools||[]}
              onToggle={v=>{const c=a.c_tools||[];set({c_tools:c.includes(v)?c.filter(x=>x!==v):[...c,v]});}} cols={2} />
            <OtherField value={a.c_toolOther} onChange={v=>set({c_toolOther:v})} placeholder="Other tool (optional)" />
          </div>
        )}
      </Field>

      {p==='it' && <>
        <Field label="What API types do you expose or consume?" missing={!(a.c_apiTypes||[]).length}><MultiCheck options={['REST APIs','SOAP Web Services','GraphQL','gRPC','Event-driven / Kafka / message broker','Webhooks','No APIs in use']} values={a.c_apiTypes||[]} onToggle={v=>{const c=a.c_apiTypes||[];set({c_apiTypes:c.includes(v)?c.filter(x=>x!==v):[...c,v]});}} cols={2} /></Field>
        <Field label="Roughly how many active API integrations do you have?" missing={!a.c_apiCount}><Radio options={['0','1–5','6–20','21–50','50+']} value={a.c_apiCount} onChange={v=>set({c_apiCount:v})} cols={2} /></Field>
        <Field label="Do you have real-time event-driven data flows?" missing={!a.c_realtime}><Radio options={[['Yes — across most systems'],['Yes — in limited areas'],['Batch / scheduled only'],['No'],['Unsure']].map(x=>x[0])} value={a.c_realtime} onChange={v=>set({c_realtime:v})} /></Field>
      </>}
      {p==='exec' && <>
        <Field label="How would you describe how your business systems share data today?" missing={!a.c_share}>
          <div className="grid gap-2">{[['manual','They mostly don\'t — we rely on manual exports or copy-paste'],['patchy','Some connect automatically, but it\'s patchy and unreliable'],['most','Most connect well and data flows without manual effort'],['realtime','Everything is connected and works in real time']].map(([k,l])=>
            <Choice key={k} selected={a.c_share===k} onClick={()=>set({c_share:k})}><span className={`text-sm ${a.c_share===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
        </Field>
        <Field label="Who keeps your system integrations working?" missing={!a.c_owner}><Radio options={['Dedicated internal integration team','External IT partner','Each team manages their own tools','No one — we fix things reactively']} value={a.c_owner} onChange={v=>set({c_owner:v})} /></Field>
      </>}
      {p==='ops' && <>
        <Field label="When a new customer comes in via website / marketing, what happens to their data?" missing={!a.c_lead}>
          <div className="grid gap-2">{[['manual','We manually enter them into our CRM or a spreadsheet'],['semi','It\'s semi-automatic but needs checking'],['auto','It flows automatically into our CRM and we trust it'],['none','We don\'t have a structured process']].map(([k,l])=>
            <Choice key={k} selected={a.c_lead===k} onClick={()=>set({c_lead:k})}><span className={`text-sm ${a.c_lead===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
        </Field>
        <Field label="To get a full picture of a customer, how many tools must you check?" missing={!a.c_view}><Radio options={['1–2 tools','3–4 tools','5 or more','We don\'t have a single customer view']} value={a.c_view} onChange={v=>set({c_view:v})} cols={2} /></Field>
      </>}
    </div>
  );
}

function StepData({ a, set, tip }) {
  const p = a.persona;
  const toggle=(key,v)=>{const c=a[key]||[];set({[key]:c.includes(v)?c.filter(x=>x!==v):[...c,v]});};
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">Tell us about your data</h2>
      <p className="text-slate-500 mb-6">Agents are only as trustworthy as the data underneath them.</p>
      <Field label="What types of data do you primarily work with? (select all)" missing={!(a.d_types||[]).length}><MultiCheck options={DATA_TYPES} values={a.d_types||[]} onToggle={v=>toggle('d_types',v)} cols={2} /></Field>
      <Field label="Most of your business-critical data is:" missing={!a.d_structure}><Radio options={STRUCTURE} value={a.d_structure} onChange={v=>set({d_structure:v})} /></Field>
      <Field label="How does new data primarily enter your systems? (select all)" missing={!(a.d_entry||[]).length}><MultiCheck options={DATA_ENTRY} values={a.d_entry||[]} onToggle={v=>toggle('d_entry',v)} cols={2} /></Field>
      {p==='it' && <>
        <Field label={<>Do you have a formal <Tip term="MDM" show={tip}>data governance</Tip> policy?</>}>
          <div className="grid gap-2">{[['formal','Yes — documented, enforced, regularly reviewed'],['informal','Yes — informal guidelines'],['partial','Partially — for some systems'],['no','No']].map(([k,l])=>
            <Choice key={k} selected={a.d_gov===k} onClick={()=>set({d_gov:k})}><span className={`text-sm ${a.d_gov===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
        </Field>
        <Field label={<>Do you have a <Tip term="MDM" show={tip}>Master Data Management (MDM)</Tip> strategy?</>}>
          <div className="grid gap-2">{[['yes','Yes — MDM is implemented'],['planning','Yes — in planning'],['partial','Partially — for some domains'],['no','No']].map(([k,l])=>
            <Choice key={k} selected={a.d_mdm===k} onClick={()=>set({d_mdm:k})}><span className={`text-sm ${a.d_mdm===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
        </Field>
      </>}
      {p==='exec' && (
        <Field label="How confident are you that your data is accurate enough to base decisions on?">
          <div className="grid gap-2">{[['very','Very confident — we have clear data governance'],['fairly','Fairly confident — it\'s mostly reliable'],['mixed','Mixed — depends on the department or data type'],['not','Not confident — data quality is a known issue']].map(([k,l])=>
            <Choice key={k} selected={a.d_confidence===k} onClick={()=>set({d_confidence:k})}><span className={`text-sm ${a.d_confidence===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
        </Field>
      )}
      {p==='ops' && (
        <Field label="How often do you find conflicting, duplicate or outdated data in your tools?">
          <div className="grid gap-2">{[['rarely','Rarely — our data is clean and up to date'],['sometimes','Sometimes — a few fields or records are wrong'],['frequently','Frequently — we often have to check and correct data'],['daily','It\'s a significant daily problem']].map(([k,l])=>
            <Choice key={k} selected={a.d_conflict===k} onClick={()=>set({d_conflict:k})}><span className={`text-sm ${a.d_conflict===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
        </Field>
      )}
    </div>
  );
}

function StepAutomation({ a, set }) {
  const simple = a.persona !== 'it';   // leadership and operations get the short form
  const G=(key,opts)=> (
    <div className="grid gap-2" data-missing={a[key]?undefined:'true'}>{opts.map(([k,l])=>
      <Choice key={k} selected={a[key]===k} onClick={()=>set({[key]:k})}><span className={`text-sm ${a[key]===k?'font-semibold text-navy':'text-slate-700'}`}>{l}</span></Choice>)}</div>
  );
  return (
    <div className="step-anim">
      <h2 className="text-2xl font-bold text-navy mb-1">Automation & AI maturity</h2>
      <p className="text-slate-500 mb-6">Where are you on the journey today?</p>
      <Field label="Do you already have automated workflows / process automation?">{G('au_workflows',[['extensive','Yes — extensively across multiple departments'],['some','Yes — in some areas'],['few','A few simple automations'],['no','No']])}</Field>
      <Field label="Have you run any AI or machine-learning pilot projects?">{G('au_pilot',[['production','Yes — AI is in production'],['pilot','Yes — a pilot or PoC'],['exploring','No — but actively exploring'],['no','No — not on our roadmap yet']])}</Field>
      <Field label="Do your AI tools (if any) have access to your live business data?">{G('au_live',[['yes','Yes — AI can query our live systems'],['partial','Partially — some data from our systems'],['no','No — AI only uses public information'],['none','We don\'t currently use AI tools']])}</Field>
      <Field label="Do you have a policy on what data AI systems may access?">{G('au_policy',[['formal','Yes — formally documented'],['informal','Yes — informal guidelines'],['planned','No — but we plan to define one'],['no','No — not considered yet']])}</Field>
      <Field label="Which controls do you have in place for AI?" missing={!((a.au_guardrails||[]).length || a.au_noGuardrails)}>
        <p className="-mt-1 mb-2 text-xs text-slate-400">
          {simple
            ? 'Most companies have none of these yet — that is the normal starting point. Tick anything you do have.'
            : 'Guardrails that keep AI safe, compliant and affordable.'}
        </p>
        <label className={`mb-2 flex items-center gap-2 rounded-xl border-2 px-4 py-2.5 text-sm transition ${a.au_noGuardrails?'border-amber-500 bg-amber-50 font-semibold text-navy':'border-slate-200 bg-white text-slate-700'}`}>
          <input type="checkbox" checked={!!a.au_noGuardrails} onChange={e=>set({au_noGuardrails:e.target.checked, au_guardrails:[]})} className="accent-amber-500" />
          None of these are in place yet
        </label>
        <MultiCheck options={AI_GUARDRAILS} values={a.au_guardrails||[]}
          onToggle={v=>{const c=a.au_guardrails||[];set({au_guardrails:c.includes(v)?c.filter(x=>x!==v):[...c,v],au_noGuardrails:false});}} />
      </Field>

    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  RESULTS                                                             */
/* ------------------------------------------------------------------ */

/* Print / "Save as PDF". Browsers expose PDF export through the print dialog,
   so we name the document first — that becomes the suggested filename. */
function printReport(a) {
  const original = document.title;
  const slug = (a.i_company || 'Company').replace(/[^\w\s-]/g,'').trim().replace(/\s+/g,'-');
  document.title = `AI-Readiness-Report-${slug}`;
  const restore = () => { document.title = original; window.removeEventListener('afterprint', restore); };
  window.addEventListener('afterprint', restore);
  setTimeout(() => { window.print(); setTimeout(restore, 1000); }, 50);
}

function Results({ a, onRestart }) {
  const res = useMemo(()=>calculateScore(a),[a]);
  const recs = useMemo(()=>recommendations(res,a),[res,a]);
  const sys = allSystems(a.systems);
  /* One node per distinct system, flagged when it already exposes an API. */
  const nodes = sys.length
    ? Object.values(sys.reduce((acc,x)=>{
        acc[x.name] = { label:x.name, api:(acc[x.name]?.api) || x.connection === 'realtime' };
        return acc;
      }, {}))
    : [{label:'CRM'},{label:'ERP'},{label:'Website'},{label:'Finance'},{label:'Support'},{label:'Email'}];
  const apiNodes = nodes.filter(n=>n.api).length;
  const breaks   = useMemo(()=>breakPoints(res,a),[res,a]);
  // Anyone who already runs a platform gets gateway advice, not another platform.
  const gwAdvice = res.architecture !== 'middleware';
  const benefits = gwAdvice ? BENEFITS_GATEWAY : BENEFITS_MIDDLEWARE;
  const roi      = gwAdvice ? ROI_COLUMNS.gateway : ROI_COLUMNS.middleware;
  const persona = PERSONAS[a.persona];

  return (
    <div className="step-anim space-y-8">
      {/* headline + gauge — always visible */}
      <div className="text-center">
        <div className="inline-flex items-center gap-2 rounded-full bg-navy px-4 py-1.5 text-xs font-semibold text-amber-400">
          <Icon name="compass" size={14} color="#FFB162" /> ASSESSMENT COMPLETE
        </div>
        <h2 className="mt-4 text-3xl sm:text-4xl font-extrabold tracking-tight text-navy">Your AI Readiness Score</h2>
        <div className="mt-1 text-sm text-slate-500">
          {a.i_company ? <>{a.i_company} · </> : null}{a.i_industry} · <span className="font-semibold text-navy">{persona?.title}</span>
        </div>
        <div className="flex justify-center my-2"><Gauge value={res.total} color={res.tierColor} /></div>
        <div className="inline-flex items-center gap-2 rounded-full px-5 py-2 text-white font-bold" style={{background:res.tierColor}}>
          <Icon name="award" size={16} color="#fff" /> {res.tierLabel} — {res.total}%
        </div>
        <p className="mt-4 max-w-xl mx-auto text-slate-600">{TIER_HEADLINE[res.tier]}</p>
      </div>

      <PartBanner n="1" title="Where you stand today"
        sub="Your score, your landscape as it is now, and the specific places it breaks." />

      {/* breakdown */}
      <Section title="Your score breakdown" icon="chart"><Bars dims={res.dimensions} /></Section>

      {/* ---- Status quo and target, side by side ---- */}
      <Section title="Your landscape today — and what it needs to become" icon="link"
        subtitle={res.hasLlm ? 'How your systems and AI connect right now, next to the target state.' : 'How your systems connect right now — you are not running AI against them yet — next to the target state.'}>
        <div className="grid md:grid-cols-2 gap-4 items-stretch">
          <div className={`flex h-full flex-col rounded-2xl border-2 p-4 ${res.hasMiddleware?'border-amber-200 bg-amber-50/50':'border-red-200 bg-red-50/40'}`}>
            <div className="flex flex-wrap items-center gap-2 mb-1">
              <Dot c={res.hasMiddleware?'#8A6A2E':'#A35139'}/>
              <span className={`text-sm font-bold ${res.hasMiddleware?'text-amber-700':'text-red-800'}`}>A · Current status</span>
              {res.hasMiddleware && <span className="rounded-full bg-amber-600 px-2 py-0.5 text-[10px] font-bold text-white">Platform in place</span>}
              {apiNodes>0 && <span className="rounded-full bg-green-600 px-2 py-0.5 text-[10px] font-bold text-white">{apiNodes} system{apiNodes>1?'s':''} with API</span>}
            </div>
            <Landscape mode="before" nodes={nodes} res={res} />
            <p className="text-xs text-slate-600 mt-1">
              {res.hasMiddleware
                ? <>You already route through <b>{res.middlewareName}</b>, so this is <b>not</b> a pure point-to-point landscape — a real head start. What it does not yet do is govern <i>AI</i> access.</>
                : <>Brittle point-to-point connections. Costly to maintain, hard to secure — <b>AI can't run reliably on this.</b> If one system changes, the connections around it break.</>}
              {!res.hasLlm && <> You have <b>no AI running against these systems yet</b>, so this is simply the ground AI would have to stand on.</>}
              {apiNodes>0 && <> <b>{apiNodes} of your systems already expose APIs</b> — that groundwork counts.</>}
            </p>
            <div className="mt-auto" />
          </div>
          <div className="flex h-full flex-col rounded-2xl border-2 border-green-200 bg-green-50/40 p-4">
            <div className="flex items-center gap-2 mb-1"><Dot c="#2E6B45"/><span className="text-sm font-bold text-green-800">B · Target state</span></div>
            <Landscape mode="after" nodes={nodes} res={res} />
            <p className="text-xs text-slate-600 mt-1">
              {res.architecture === 'platform-gateway'
                ? <>Keep <b>{res.middlewareName}</b> as your Integration &amp; Orchestration Layer at the centre, and add a separate <b>AI Gateway</b> above it — authentication, rate limiting, policy and logging for AI specifically.</>
                : res.architecture === 'gateway'
                ? <>With {res.totalSystems} system{res.totalSystems===1?'':'s'} and no ERP or data warehouse behind them, you do <b>not</b> need a full integration platform. An <b>AI Gateway</b> sitting directly under your AI, connecting out to each system, is enough.</>
                : <>An <b>Integration &amp; Orchestration Layer</b> at the centre of your systems — one governed, reusable connection each — before AI governance is added on top.</>}
            </p>
            <p className="mt-2 rounded-lg bg-green-50 px-3 py-2 text-xs font-semibold text-green-800">
              {res.architecture === 'middleware'
                ? 'The nervous system first — then agents can be trusted to act through it.'
                : 'Governs how agents access enterprise systems and data.'}
            </p>
          </div>
        </div>
      </Section>

      {/* ---- Where it breaks ---- */}
      {breaks.length>0 && (
        <Section title="Where this breaks" icon="zap"
          subtitle="Read from your own answers — these are the specific points where AI would fail today.">
          <div className="space-y-3">
            {breaks.map(([t,d],i)=>(
              <div key={i} className="rounded-xl border-l-4 border-red-500 bg-white p-4 shadow-sm">
                <p className="font-bold text-navy">{t}</p>
                <p className="mt-1 text-sm text-slate-600">{d}</p>
              </div>
            ))}
          </div>
        </Section>
      )}

      <PartBanner n="2" title="What to do about it"
        sub="The architecture your landscape actually calls for, and the order to build it in." />

      <Section title={ARCH_TITLE[res.architecture]} icon="layers"
        subtitle={ARCH_SUB[res.architecture]}>
        <div className="rounded-2xl border border-slate-200 bg-white p-5">
          <p className="text-slate-700">
            {res.architecture === 'platform-gateway'
              ? <>You already run <b>{res.middlewareName}</b>. Treat it as your <b>Integration &amp; Orchestration Layer</b> — the nervous system at the centre of your systems — and add a <b>separate AI Gateway</b> above it. They are two different jobs: one moves and governs data between systems, the other governs what AI is allowed to do with it.</>
              : res.architecture === 'gateway'
              ? <>Your landscape is light enough that connecting it is not the bottleneck — control is. An <b>AI Gateway</b> directly beneath your AI, calling each system, gives you authentication, spend limits, policy and logging without a full integration programme.</>
              : <>You run {res.bigSystems.length>=2 ? <>{res.bigSystems.length} core systems</> : <>{res.totalSystems} systems</>} with nothing joining them up. The <b>Integration &amp; Orchestration Layer comes first</b>: one governed connection per system, sitting at the centre rather than on top, exposing each as a clean reusable API. AI governance is added onto that afterwards — not instead of it.</>}
          </p>
        </div>
        {!gwAdvice && (
          <div className="grid grid-cols-2 sm:grid-cols-3 gap-3 mt-4">
            {benefits.map(([n,l])=>(
              <div key={l} className="rounded-xl bg-navy text-center px-3 py-3">
                <div className="text-lg font-extrabold text-amber-400">{n}</div>
                <div className="text-[11px] text-slate-300 leading-tight mt-0.5">{l}</div>
              </div>
            ))}
          </div>
        )}
      </Section>

      {/* ROI: custom code vs API-led */}
      <Section title={gwAdvice ? 'Ungoverned AI access vs. an AI Gateway' : 'Custom point-to-point vs. structured connectivity (Real-time API)'} icon="trending">
        <div className="grid sm:grid-cols-2 gap-4">
          <div className="rounded-2xl border border-red-200 p-4">
            <div className="text-sm font-bold text-red-800 mb-2">Without {gwAdvice ? 'an AI Gateway' : 'an Integration & Orchestration Layer'}</div>
            <ul className="text-sm text-slate-600 space-y-1.5">
              {roi.without.map(x=><li key={x} className="flex gap-2"><span className="text-red-500">✕</span>{x}</li>)}
            </ul>
          </div>
          <div className="rounded-2xl border border-green-200 p-4">
            <div className="text-sm font-bold text-green-800 mb-2">With {gwAdvice ? 'an AI Gateway' : 'an Integration & Orchestration Layer'}</div>
            <ul className="text-sm text-slate-600 space-y-1.5">
              {roi.with.map(x=><li key={x} className="flex gap-2"><span className="text-green-600">✓</span>{x}</li>)}
            </ul>
          </div>
        </div>
        <div className="mt-4 rounded-2xl bg-amber-50 border border-amber-200 p-5 text-center">
          <div className="text-xs font-semibold uppercase tracking-wide text-amber-700">{gwAdvice ? 'What this buys you' : 'Illustrative 5-year impact'}</div>
          <div className="mt-1 flex flex-wrap justify-center gap-x-10 gap-y-2">
            {roi.stats.map(([v,l])=>(
              <div key={l}><span className="text-3xl font-extrabold text-navy">{v}</span><div className="text-xs text-slate-500">{l}</div></div>
            ))}
          </div>
          <div className="text-[11px] text-slate-400 mt-2">{roi.note}</div>
        </div>
      </Section>

      {/* ---- Which layer you actually need, given your APIs ---- */}
      <Section title="What you actually need to build" icon="layers"
        subtitle="Your starting point decides how much work this is.">
        {res.apiPosture === 'strong' ? (
          <div className="rounded-2xl border-2 border-green-200 bg-green-50/50 p-5">
            <div className="flex items-center gap-2">
              <span className="rounded-full bg-green-600 px-3 py-1 text-xs font-bold text-white">Good news — you already have APIs</span>
            </div>
            <p className="mt-3 text-slate-700">
              {byRole(a.persona, {
                it:  <>Your systems already expose programmatic interfaces, so <b>the integration half of the problem is largely solved</b>. Building a full iPaaS on top would duplicate work you have already done.</>,
                exec:<>Your systems can already be reached automatically, so <b>you probably don't need a full integration platform to connect them</b>. The expensive groundwork is largely done.</>,
                ops: <>Your systems can already talk to other software automatically — <b>the hard plumbing is mostly there</b>.</>,
              })}
            </p>
            <p className="mt-2 text-slate-700">
              What you're missing is the layer <i>above</i> them: an <b>AI Orchestration Layer</b> —
              a single control plane that governs traffic, decides which agent may call which API,
              enforces security and limits, and logs everything.
            </p>
            <p className="mt-3 rounded-lg bg-white px-3 py-2 text-sm font-semibold text-green-800">
              This is considerably less work than a full middleware programme — you are building
              governance on top of what already exists, not rebuilding the plumbing.
            </p>
          </div>
        ) : res.apiPosture === 'partial' ? (
          <div className="rounded-2xl border-2 border-amber-200 bg-amber-50 p-5">
            <div className="flex items-center gap-2">
              <span className="rounded-full bg-amber-600 px-3 py-1 text-xs font-bold text-white">Partly there</span>
            </div>
            <p className="mt-3 text-slate-700">
              Some of your systems are reachable through APIs, others are not. The efficient path is to
              <b> API-enable the remaining core systems first</b>, then put a single
              <b> Integration &amp; Orchestration Layer</b> across all of them — rather than building
              one-off connections for each.
            </p>
          </div>
        ) : (
          <div className="rounded-2xl border-2 border-red-200 bg-red-50/50 p-5">
            <div className="flex items-center gap-2">
              <span className="rounded-full bg-red-600 px-3 py-1 text-xs font-bold text-white">Foundations first</span>
            </div>
            <p className="mt-3 text-slate-700">
              Your systems are not yet reachable programmatically, so AI has no safe way in. Start by
              making your two or three most important systems accessible, then govern them through one
              <b> Integration &amp; Orchestration Layer</b> instead of wiring point-to-point.
            </p>
          </div>
        )}
      </Section>

      {/* ---- Security & compliance: the risk of running AI ungoverned ---- */}
      {res.securityRisk !== 'low' && (
        <Section title="Security &amp; compliance gaps" icon="shield"
          subtitle="What is missing today if AI starts touching your systems.">
          <div className="rounded-2xl border-2 border-red-200 bg-white p-5">
            <div className="flex flex-wrap items-center gap-2">
              <span className="rounded-full px-3 py-1 text-xs font-bold text-white"
                style={{background: res.securityRisk === 'high' ? '#8F3D2A' : '#C0662F'}}>
                {res.securityRisk === 'high' ? 'High exposure' : 'Partial cover'}
              </span>
              <span className="text-sm text-slate-500">
                {res.guardrailCount} of {AI_GUARDRAILS.length} controls in place
                {!res.hasMiddleware && ' · no integration platform'}
              </span>
            </div>

            <p className="mt-4 text-slate-700">
              {res.hasMiddleware
                ? byRole(a.persona, {
                    it:  'You have a platform to build on, but the AI-specific controls are not in place. Each gap is an unbounded call path, an unlogged action, or an unmetered cost.',
                    exec:'You have a platform to build on, but several controls are still missing. Each one is a place where AI can cost more than expected, or reach data it should not.',
                    ops: 'You already have a tool that connects your systems — but nothing yet that limits what AI can see, do or spend.',
                  })
                : byRole(a.persona, {
                    it:  'Without a gateway, every AI tool holds its own credentials and calls your systems directly. There is no central place to enforce scope, apply rate limits, or reconstruct what happened.',
                    exec:'Without a governing layer, every AI tool connects directly to your systems with its own credentials and its own rules. There is no single place to see what it accessed, cap what it costs, or prove compliance.',
                    ops: 'At the moment each AI tool connects on its own terms. Nobody can see what it looked at, stop it going too far, or say what it cost.',
                  })}
            </p>

            <p className="mt-4 text-sm font-bold text-navy">Missing today:</p>
            <ul className="mt-2 space-y-1.5">
              {res.securityGaps.map(g => (
                <li key={g} className="flex gap-2 text-sm text-slate-600"><span className="text-red-500">✕</span>{g}</li>
              ))}
            </ul>

            <div className="mt-5 rounded-xl bg-cream p-4">
              <p className="text-sm font-bold text-navy">Why this matters now</p>
              <ul className="mt-2 space-y-1.5 text-sm text-slate-600">
                <li className="flex gap-2"><span className="text-amber-600">•</span><span><b>Cost control.</b> Without token and consumption limits, AI usage scales with no ceiling — the bill arrives after the fact.</span></li>
                <li className="flex gap-2"><span className="text-amber-600">•</span><span><b>GDPR &amp; the EU AI Act.</b> You need to show which data AI processed and on what basis. Masking personal data before it reaches a model, and a data processing agreement with your provider, are the usual expectations.</span></li>
                <li className="flex gap-2"><span className="text-amber-600">•</span><span><b>Access boundaries.</b> A documented decision on what AI may and may not read — salary data, customer contracts, health records — enforced in one place rather than trusted to each tool.</span></li>
                <li className="flex gap-2"><span className="text-amber-600">•</span><span><b>API policy.</b> Rate limiting and OAuth scopes stop one misbehaving agent from overwhelming a production system or reaching beyond its remit.</span></li>
                <li className="flex gap-2"><span className="text-amber-600">•</span><span><b>Audit trail.</b> If you cannot show what the AI did, you cannot defend it — to a customer, an auditor, or a regulator.</span></li>
              </ul>
              <p className="mt-3 text-sm font-semibold text-navy">
                These are exactly the controls an Integration &amp; Orchestration Layer centralises. Without one,
                each has to be solved separately in every tool — or not at all.
              </p>
            </div>
          </div>
        </Section>
      )}

      {/* ---- What an AI Gateway covers — only where one is recommended ---- */}
      {gwAdvice && (
      <Section title="What an AI Gateway covers" icon="shield"
        subtitle={byRole(a.persona, {
          it:  'The control plane between your agents and your systems — five capabilities that matter most.',
          exec:'The five things this layer gives you that are hard to retrofit later.',
          ops: 'What this layer actually does for you, in plain terms.',
        })}>
        <div className="rounded-2xl border border-slate-200 bg-white p-5">
          <p className="text-slate-700">
            {byRole(a.persona, {
              it:  <>An AI Gateway is the enforcement point every agent call passes through. It can be a standalone layer or a capability of your Integration &amp; Orchestration Layer — either way, it is where identity, limits, policy and logging are applied once instead of per integration.</>,
              exec:<>An AI Gateway is the single point every AI request passes through. It can sit inside your integration platform or stand alone. Its value is that control, cost and evidence live in one place — which is what makes AI safe to scale beyond a pilot.</>,
              ops: <>An AI Gateway is a checkpoint that every AI request goes through. It is what turns "we are trying an AI tool" into something you can rely on day to day without worrying about cost, mistakes or data leaking.</>,
            })}
          </p>
          <div className="mt-4 grid sm:grid-cols-2 gap-3">
            {GATEWAY_COVERS.map(g => (
              <div key={g.title.exec} className="rounded-xl bg-cream p-4">
                <div className="flex items-center gap-2">
                  <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-amber-100">
                    <Icon name={g.icon} size={15} color="#A35139" strokeWidth={2} />
                  </span>
                  <span className="font-bold text-navy">{byRole(a.persona, g.title)}</span>
                </div>
                <p className="mt-2 text-sm text-slate-600">{byRole(a.persona, g.body)}</p>
              </div>
            ))}
          </div>
          <div className="mt-5 rounded-xl bg-cream p-4">
            <p className="text-sm font-bold text-navy">Three ways it pays for itself</p>
            <ol className="mt-2 space-y-2 text-sm text-slate-600">
              <li className="flex gap-2"><span className="font-bold text-amber-600">1.</span><span><b>Lower running cost.</b> Caching repeated prompts and routing simple queries to cheaper models cuts blended cost per request — automatic once the gateway exists, instead of a decision made project by project.</span></li>
              <li className="flex gap-2"><span className="font-bold text-amber-600">2.</span><span><b>Incidents avoided.</b> Guardrails and personal-data controls at the boundary reduce the chance of a costly leak. Priced against even one avoided incident, it usually dwarfs what the layer costs to run.</span></li>
              <li className="flex gap-2"><span className="font-bold text-amber-600">3.</span><span><b>Faster delivery.</b> The next team building the next agent inherits auth, limits, logging and routing instead of solving them again — real engineering weeks saved per use case, compounding as you build more.</span></li>
            </ol>
          </div>

          <p className="mt-4 text-sm text-slate-600">
            <b className="text-navy">Why now:</b> autonomous agents break the assumption traditional API
            infrastructure was built on — predictable, human-initiated requests. That exposes gaps in
            token visibility, policy coverage and audit trails. Adding a standalone gateway per tool
            deepens the fragmentation; one shared policy layer across whatever gateways you already run
            is what closes it, since governance gaps form at the seams between tools.
          </p>

          <p className="mt-4 text-sm font-semibold text-navy">
            {res.hasMiddleware
              ? <>You already have {res.middlewareName} to build on — the gateway is the layer you add on top of it, not a replacement. There is no case for a second integration platform.</>
              : <>None of this exists by default. Every AI tool you add without it is another set of credentials, another uncapped bill and another blind spot.</>}
          </p>
        </div>
      </Section>
      )}

      {/* ---- Sector-specific obligations ---- */}
      {INDUSTRY_RULES[a.i_industry] && (
        <Section title={`Because you work with ${INDUSTRY_RULES[a.i_industry].label}`} icon="shield"
          subtitle={`Extra obligations that apply to ${a.i_industry.toLowerCase()} — and that AI does not exempt you from.`}>
          <div className="rounded-2xl border-2 border-amber-300 bg-amber-50/60 p-5">
            <p className="text-slate-700">{INDUSTRY_RULES[a.i_industry].intro}</p>
            <div className="mt-4 space-y-3">
              {INDUSTRY_RULES[a.i_industry].points.map(([t,d]) => (
                <div key={t}>
                  <p className="text-sm font-bold text-navy">{t}</p>
                  <p className="text-sm text-slate-600">{d}</p>
                </div>
              ))}
            </div>
            <p className="mt-4 rounded-lg bg-white px-3 py-2 text-sm text-slate-700">
              <b>Practical consequence:</b> in your sector, the governing layer is not an optimisation — it is
              where masking, access rules, logging and provider contracts are actually enforced. Regulators
              ask you to evidence these, and evidence is much easier to produce from one place than from
              a dozen tools.
            </p>
            <p className="mt-2 text-[11px] text-slate-400">
              General orientation, not legal advice — confirm the specifics with your data-protection officer or counsel.
            </p>
          </div>
        </Section>
      )}

      {/* recommendations */}
      <Section title="Your top recommendations" icon="target" subtitle={`Focused on your weakest area: ${DIM_LABELS[res.weakestDimension]}.`}>
        <div className="grid gap-3">
          {recs.map((r,i)=>{
            const mentionsMcp = /MCP/.test(r.title + r.body);
            return (
              <div key={i} className="rounded-2xl border border-slate-200 bg-white p-4 flex gap-3">
                <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-amber-500 font-bold text-navy">{i+1}</div>
                <div className="min-w-0">
                  <div className="font-bold text-navy">
                    {r.title}
                    {mentionsMcp && <Help title="What is an MCP server?" label="What is an MCP server?">{MCP_EXPLAINER}</Help>}
                  </div>
                  <p className="text-sm text-slate-600 mt-1">{r.body}</p>
                </div>
              </div>
            );
          })}
        </div>
      </Section>

      {/* MCP readiness — explained in plain language */}
      <Section title="Can AI safely plug into your business?" icon="plug"
        subtitle="Your MCP readiness — the standard way AI connects to company systems.">
        <div className="rounded-2xl border border-slate-200 bg-white p-5">
          <div className="flex items-center gap-3 flex-wrap">
            <div className="flex items-center gap-1.5">
              {[1,2,3,4,5].map(i=><span key={i} className="h-3 w-8 rounded-full" style={{background:i<=res.bonus?res.tierColor:'#DDD8CC'}} />)}
            </div>
            <span className="font-bold text-navy">{res.bonus}/5</span>
            <span className="rounded-full px-3 py-1 text-xs font-bold text-white" style={{background:res.mcpReady?'#2E6B45':'#A35139'}}>
              {res.mcpReady ? 'Ready to connect' : 'Not ready yet'}
            </span>
          </div>

          <div className="mt-4 grid sm:grid-cols-2 gap-4">
            <div className="rounded-xl bg-cream p-4">
              <div className="flex items-center gap-2 text-sm font-bold text-navy mb-1"><Icon name="plug" size={16} color="#A35139" /> What it is</div>
              <p className="text-sm text-slate-600">
                Think of it as a <b>secure power socket for AI</b>. Instead of a custom wire to every AI tool,
                it gives any AI assistant <b>one safe, controlled doorway</b> into your business systems —
                and you decide exactly what it may see and do.
              </p>
            </div>
            <div className="rounded-xl bg-cream p-4">
              <div className="flex items-center gap-2 text-sm font-bold text-navy mb-1"><Icon name="shield" size={16} color="#A35139" /> Why it matters</div>
              <p className="text-sm text-slate-600">
                It's the difference between AI that <i>talks about</i> your business and AI that
                <b> actually works in it</b> — looking up a real order, updating a record, answering from
                today's numbers instead of guessing. Without it, every AI project is rebuilt from scratch.
              </p>
            </div>
          </div>

          <p className="mt-4 text-sm text-slate-600">
            {res.mcpReady
              ? 'Your systems are structurally ready: you can open this doorway and let AI work with your live data under your rules.'
              : 'To get there: make your key systems reachable automatically, put one secured gateway in front of them, and write down which data AI is allowed to use.'}
          </p>
        </div>
      </Section>

      {/* systems entered */}
      {sys.length>0 && (
        <Section title="Systems you entered" icon="grid" subtitle="Colour = connection status.">
          <div className="flex flex-wrap gap-2">
            {sys.map((s,i)=>{const m=connMeta(s.connection);return (
              <span key={i} className="inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium" style={{borderColor:m.color,color:'#2C3B4D'}}>
                <span className="h-2 w-2 rounded-full" style={{background:m.color}} />{s.name}
              </span>);})}
          </div>
          <div className="flex flex-wrap gap-3 mt-3 text-[11px] text-slate-500">
            {CONNECTIONS.map(c=><span key={c.key} className="flex items-center gap-1"><span className="h-2 w-2 rounded-full" style={{background:c.color}} />{c.label}</span>)}
          </div>
        </Section>
      )}

      {/* ---- The honest caveat, when we did not recommend middleware ---- */}
      {gwAdvice && (
        <Section title="One honest caveat about skipping the integration layer" icon="compass"
          subtitle="Worth knowing now rather than in eighteen months.">
          <div className="rounded-2xl border border-slate-200 bg-white p-5">
            <div className="grid sm:grid-cols-2 gap-3">
              <div className="rounded-xl bg-cream p-4">
                <p className="font-bold text-navy">The orchestration layer is the brain</p>
                <p className="mt-1 text-sm text-slate-600">It plans, reasons and decides what to do next. That is what an AI Gateway and an agent framework give you.</p>
              </div>
              <div className="rounded-xl bg-cream p-4">
                <p className="font-bold text-navy">The integration layer is the nervous system</p>
                <p className="mt-1 text-sm text-slate-600">It executes reliably and securely against real systems, and exposes them as clean, reusable, governed APIs — which then simply look like "tools" to the brain.</p>
              </div>
            </div>
            <p className="mt-4 text-slate-700">
              {byRole(a.persona, {
                it:  <>Connecting an LLM straight to raw systems works — until you hit scale, security review, or the first breaking schema change. Most teams that start direct end up building a middleware layer anyway within 12–18 months, usually without calling it that, and usually under time pressure. Orchestration does not stop working without it; it works <b>better and more safely when it is calling governed APIs instead of raw systems</b>.</>,
                exec:<>Going direct is a legitimate way to start, and for your landscape it is the right call today. The honest caveat: almost every company that starts this way rebuilds an integration layer 12–18 months later — usually when growth, an audit, or a system change forces it. That is not a reason to build it now. It is a reason to keep the option open and avoid decisions that make it harder later.</>,
                ops: <>Starting simple is the right call for you. Be aware, though: as you add systems and more people rely on it, most companies reach a point where they need a proper connection layer underneath. That is normal, and nothing you do now has to make it harder later.</>,
              })}
            </p>
            <p className="mt-3 rounded-lg bg-amber-50 px-3 py-2 text-sm font-semibold text-navy">
              Practical guidance: build the gateway now, and keep your integrations behind clean interfaces so
              they can move under a proper integration layer later without rewriting your agents.
            </p>
          </div>
        </Section>
      )}

      {/* CTA */}
      <div className="rounded-3xl bg-navy p-8 text-center text-white">
        <h3 className="text-2xl font-bold">Ready to take the next step?</h3>
        <p className="mt-2 text-slate-300 max-w-lg mx-auto">Book a free 30-minute AI Architecture Review to turn this assessment into a concrete, vendor-neutral roadmap.</p>
        <div className="no-print mt-6 flex flex-wrap justify-center gap-3">
          <a href={CONFIG.bookingUrl} target="_blank" rel="noopener noreferrer"><Btn>Book a Call</Btn></a>
          <Btn variant="ghost" className="!text-white !border-white/40 hover:!border-white" onClick={()=>printReport(a)}>Download / Print Results</Btn>
          <Btn variant="ghost" className="!text-white !border-white/40 hover:!border-white" onClick={onRestart}>Start Over</Btn>
        </div>
        <p className="mt-4 text-[11px] text-slate-400">When to use what: direct point-to-point is fine for 1–2 simple systems. An integration layer pays off at 3+ systems, complex processes, or when you need security, monitoring, reusability — and AI on top.</p>
      </div>

      {/* print-only footer */}
      <div className="hidden print:block text-center text-[10px] text-slate-500">
        {CONFIG.brandName} · AI readiness report for {a.i_company} · generated {new Date().toLocaleDateString()}
      </div>
    </div>
  );
}

const PartBanner = ({ n, title, sub }) => (
  <div className="mt-4 flex items-center gap-3 rounded-2xl bg-navy px-5 py-4">
    <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-amber-500 text-base font-extrabold text-navy">{n}</span>
    <div>
      <p className="text-[11px] font-bold uppercase tracking-wider text-amber-400">Part {n}</p>
      <p className="font-bold text-white">{title}</p>
      <p className="text-xs text-slate-300">{sub}</p>
    </div>
  </div>
);

const Dot = ({c}) => <span className="inline-block h-2.5 w-2.5 rounded-full" style={{background:c}} />;
const Section = ({ title, subtitle, icon, children }) => (
  <section>
    <h3 className="flex items-center gap-2 text-lg font-bold text-navy">
      {icon && <span className="flex h-7 w-7 items-center justify-center rounded-lg bg-amber-100"><Icon name={icon} size={15} color="#A35139" strokeWidth={2} /></span>}
      {title}
    </h3>
    {subtitle && <p className="text-sm text-slate-500 mt-0.5 mb-3">{subtitle}</p>}
    {!subtitle && <div className="mb-3" />}
    {children}
  </section>
);

/* ------------------------------------------------------------------ */
/*  ROOT APP                                                            */
/* ------------------------------------------------------------------ */

const initialAnswers = { v_goals:[], v_facing:[], systems:{}, d_types:[], d_entry:[], c_apiTypes:[],
  c_hasTools:"None — we don't use one", c_tools:[], au_guardrails:[] };

function App() {
  const [step, setStep] = useState(0);      // 0 welcome, 1..7 steps, 8 results
  const [maxStep, setMaxStep] = useState(0); // furthest step reached — everything up to here stays clickable
  const [a, setA] = useState(initialAnswers);
  const go = (n) => { setStep(n); setMaxStep(m => Math.max(m, n)); };
  const set = (patch) => setA(prev => ({ ...prev, ...patch }));
  const tip = a.persona && a.persona !== 'it'; // tooltips for non-technical personas
  const topRef = useRef(null);
  useEffect(()=>{
    // Come back to a half-finished stage and land on the first unanswered
    // question rather than the top of the page.
    const t = setTimeout(()=>{
      const missing = document.querySelector('[data-missing="true"]');
      if (missing && step >= 1 && step <= 7) missing.scrollIntoView({behavior:'smooth', block:'center'});
      else topRef.current && topRef.current.scrollIntoView({behavior:'smooth', block:'start'});
    }, 60);
    return ()=>clearTimeout(t);
  }, [step]);

  /* Forward requires a real answer; backward is always free.
     The same check drives the stepper, so a half-finished stage stays visibly
     in progress instead of looking done. */
  const stepComplete = (n, a) => {
    switch(n){
      case 1: return !!(a.i_industry && a.i_size && a.i_itFunction);
      /* falls through to the shared cases below */
      case 2: return !!a.persona;
      case 3: return (a.v_goals||[]).length>0 && a.v_ambition!==undefined && !!a.v_timeline && !!a.v_budget;
      case 4: return true; // "None" everywhere is a valid answer
      case 5:
        const toolsOk = a.c_hasTools === 'Yes — we use one or more'
          ? (a.c_tools||[]).length > 0
          : !!a.c_hasTools;
        if (!toolsOk) return false;
        if (a.persona==='it')   return !!((a.c_apiTypes||[]).length>0 && a.c_apiCount && a.c_realtime);
        if (a.persona==='exec') return !!(a.c_share && a.c_owner);
        return !!(a.c_lead && a.c_view);
      case 6: {
        const base = (a.d_types||[]).length>0 && !!a.d_structure && (a.d_entry||[]).length>0;
        if (a.persona==='it')   return base && !!a.d_gov && !!a.d_mdm;
        if (a.persona==='exec') return base && !!a.d_confidence;
        return base && !!a.d_conflict;
      }
      case 7: return !!(a.au_workflows && a.au_pilot && a.au_live && a.au_policy
                        && ((a.au_guardrails||[]).length>0 || a.au_noGuardrails));
      default: return true;
    }
  };
  const canContinue = () => stepComplete(step, a);

  const stepIndexForProgress = Math.min(step===0?0:step-1, 7);
  const missingHint = !canContinue() ? 'Please answer every question on this page to continue.' : '';

  return (
    <div className="min-h-screen py-8 px-4">
      <div ref={topRef} />
      <div className="mx-auto w-full max-w-[820px]">
        {step!==0 && (
          <div className="no-print mb-4">
            <button onClick={()=>setStep(0)} title="Back to the start page"
              className="inline-flex items-center gap-2 rounded-xl border border-slate-200 bg-white px-3.5 py-2 text-sm font-bold text-navy transition hover:border-navy hover:bg-navy hover:text-cream">
              <Icon name="compass" size={16} /> AI Readiness Compass
            </button>
          </div>
        )}
        {step===-1 ? <About onBack={()=>setStep(0)} onStart={()=>go(1)} />
         : step===0 ? <Welcome onStart={()=>go(1)} onAbout={()=>setStep(-1)} /> : (
          <div className="print-card rounded-3xl bg-white shadow-xl shadow-navy/5 border border-slate-100 p-6 sm:p-9">
            <div className="no-print">
              <Progress step={stepIndexForProgress} maxStep={maxStep} onJump={(i)=>go(i+1)}
                statusOf={(i)=> (i+1) > maxStep ? 'todo' : (stepComplete(i+1, a) ? 'done' : 'partial')} />
            </div>
            {step===1 && <StepCompany a={a} set={set} />}
            {step===2 && <StepPersona a={a} set={set} />}
            {step===3 && <StepVision a={a} set={set} tip={tip} />}
            {step===4 && <StepSystems a={a} set={set} tip={tip} />}
            {step===5 && <StepConnectivity a={a} set={set} tip={tip} />}
            {step===6 && <StepData a={a} set={set} tip={tip} />}
            {step===7 && <StepAutomation a={a} set={set} />}
            {step===8 && <Results a={a} onRestart={()=>{setA(initialAnswers);setMaxStep(0);setStep(0);}} />}
            {step>=1 && step<=7 && (
              <div className="mt-8">
                {missingHint && <p className="mb-3 text-right text-xs text-slate-400">{missingHint}</p>}
                <div className="flex items-center justify-between">
                  <Btn variant="ghost" onClick={()=>go(Math.max(0, step-1))}>← Back</Btn>
                  <Btn onClick={()=>go(step+1)} disabled={!canContinue()}>{step===7?'See my score →':'Continue →'}</Btn>
                </div>
              </div>
            )}
            {step===8 && (
              <div className="no-print mt-8 border-t border-slate-100 pt-6">
                <Btn variant="ghost" onClick={()=>go(7)}>← Back to my answers</Btn>
              </div>
            )}
          </div>
        )}
        <div className="no-print mt-6 text-center text-xs text-slate-400">
          <p>{CONFIG.brandName} · vendor-neutral AI readiness assessment</p>
          <p className="mt-1 flex flex-wrap items-center justify-center gap-x-3 gap-y-1">
            <button onClick={()=>setStep(-1)} className="underline hover:text-navy">What is it?</button>
            <span aria-hidden="true">·</span>
            <a href={CONFIG.privacyUrl} className="underline hover:text-navy">Privacy policy</a>
            <span aria-hidden="true">·</span>
            <a href={CONFIG.imprintUrl} className="underline hover:text-navy">Imprint</a>
            <span aria-hidden="true">·</span>
            <a href={`mailto:${CONFIG.contactEmail}`} className="underline hover:text-navy">{CONFIG.contactEmail}</a>
          </p>
        </div>
      </div>
    </div>
  );
}


createRoot(document.getElementById('root')).render(<App />);
