/* global React, ReactDOM */
const { useState, useEffect, useRef, useLayoutEffect, useMemo } = React;

// ─────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────
function useInView(opts = {}) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (!ref.current || seen) return;
    // If the element is already in (or near) the viewport at mount,
    // trigger immediately. This handles hero content on mobile, and
    // any section that doesn't move enough to trip the observer.
    const rect = ref.current.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (rect.top < vh && rect.bottom > 0) {
      setSeen(true);
      return;
    }
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) { setSeen(true); obs.disconnect(); }
        });
      },
      { threshold: opts.threshold ?? 0.15, rootMargin: opts.rootMargin ?? '0px 0px -10% 0px' }
    );
    obs.observe(ref.current);
    // Safety fallback: if the observer hasn't fired within 1.5s, reveal anyway.
    const fallback = setTimeout(() => { setSeen(true); obs.disconnect(); }, 1500);
    return () => { obs.disconnect(); clearTimeout(fallback); };
  }, [seen]);
  return [ref, seen];
}

function useCountUp(target, duration = 1400, start = false) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!start) return;
    if (target === '∞') { setVal('∞'); return; }
    let raf, t0;
    const tick = (t) => {
      if (!t0) t0 = t;
      const p = Math.min(1, (t - t0) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setVal(Math.round(target * eased));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target, start, duration]);
  return val;
}

function WordReveal({ text, delay = 0, as = 'span', className = '' }) {
  const [ref, seen] = useInView({ threshold: 0.2 });
  const Tag = as;
  const words = text.split(' ');
  return (
    <Tag ref={ref} className={className}>
      {words.map((w, i) => (
        <React.Fragment key={i}>
          <span
            className={`word ${seen ? 'in' : ''}`}
            style={{ transitionDelay: `${delay + i * 60}ms` }}
            dangerouslySetInnerHTML={{ __html: w }}
          />
          {i < words.length - 1 ? ' ' : ''}
        </React.Fragment>
      ))}
    </Tag>
  );
}

// ─────────────────────────────────────────────────────────────
// HERO
// ─────────────────────────────────────────────────────────────
function Hero() {
  const gridRef = useRef(null);
  const stageRef = useRef(null);
  const panelRef = useRef(null);

  // Parallax cursor on grid + tilt on panel
  useEffect(() => {
    const onMove = (e) => {
      const w = window.innerWidth;
      const h = window.innerHeight;
      const nx = (e.clientX - w / 2) / (w / 2); // -1 .. 1
      const ny = (e.clientY - h / 2) / (h / 2);
      if (gridRef.current) {
        gridRef.current.style.transform = `translate3d(${nx * -18}px, ${ny * -12}px, 0)`;
      }
      if (panelRef.current && stageRef.current) {
        const r = stageRef.current.getBoundingClientRect();
        const px = (e.clientX - r.left - r.width / 2) / (r.width / 2);
        const py = (e.clientY - r.top - r.height / 2) / (r.height / 2);
        const cx = Math.max(-1, Math.min(1, px));
        const cy = Math.max(-1, Math.min(1, py));
        panelRef.current.style.transform =
          `perspective(1800px) rotateX(${-cy * 3}deg) rotateY(${cx * 4}deg) translateZ(0)`;
      }
    };
    const onLeave = () => {
      if (panelRef.current) panelRef.current.style.transform = 'perspective(1800px) rotateX(0) rotateY(0)';
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseleave', onLeave);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseleave', onLeave);
    };
  }, []);

  // Live ticking team scores in the panel
  const [scores, setScores] = useState({ a: 88, b: 61, c: 74, d: 42 });
  useEffect(() => {
    const id = setInterval(() => {
      setScores((s) => ({
        a: Math.max(70, Math.min(94, s.a + (Math.random() * 4 - 2))),
        b: Math.max(48, Math.min(72, s.b + (Math.random() * 5 - 2.5))),
        c: Math.max(60, Math.min(82, s.c + (Math.random() * 4 - 2))),
        d: Math.max(32, Math.min(54, s.d + (Math.random() * 6 - 2))),
      }));
    }, 2400);
    return () => clearInterval(id);
  }, []);

  // Cycling feed
  const allFeeds = [
    { av: 'blue', initials: 'KP', from: 'Kevin Park', target: 'Team Alpha', preview: 'Re: Data quality concerns - your framing was sharp.', badge: '+8', cls: 'badge-pos' },
    { av: 'teal', initials: 'SL', from: 'Sarah Liu',  target: 'Team Bravo', preview: 'The margin analysis lacks a clear so-what.', badge: '-4', cls: 'badge-neg' },
    { av: 'gold', initials: 'AC', from: 'AI Coach',   target: 'Team Delta', preview: 'Lead with the recommendation, then evidence.', badge: 'Coach', cls: 'badge-coach' },
    { av: 'plum', initials: 'DM', from: 'David Marsh',target: 'Team Charlie', preview: 'Impressive cost build-up. Where is the risk lens?', badge: '+6', cls: 'badge-pos' },
    { av: 'blue', initials: 'KP', from: 'Kevin Park', target: 'Team Charlie', preview: 'Push back on the FY24 forecast - assumptions are thin.', badge: '-2', cls: 'badge-neg' },
  ];
  const [feedStart, setFeedStart] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setFeedStart((i) => (i + 1) % allFeeds.length), 3600);
    return () => clearInterval(id);
  }, []);
  const visibleFeed = [0,1,2].map(i => allFeeds[(feedStart + i) % allFeeds.length]);

  return (
    <section className="hero" id="hero">
      <div className="hero-grid" ref={gridRef}></div>
      <div className="hero-aurora"></div>

      <div className="hero-inner">
        <div className="hero-eyebrow">
          <span className="eb-dot"></span>
          Booking new cohorts for 2026/27 academic year now
        </div>

        <h1 className="hero-h1">
          The consulting<br/>
          simulation used by <em>leading business schools</em>
        </h1>

        <p className="hero-sub">
          Give your MBA and executive students a real engagement - not a case study.<br/><br/>
          <strong>Project Northstar</strong> puts teams in the seat of an Engagement Manager with AI-powered clients, live scoring, and a board presentation.
        </p>

        <div className="hero-actions">
          <a href="#contact" className="btn-primary">
            Book a Demo
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 7h8m0 0L7.5 3.5M11 7l-3.5 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </a>
          <a href="#how" className="btn-ghost">See how it works →</a>
        </div>

        <div className="hero-trust gold">
          <span className="ht-rule"></span>
          Designed &amp; delivered by <em>former McKinsey</em> Engagement Managers
          <span className="ht-rule"></span>
        </div>
      </div>

      {/* Product preview panel */}
      <div className="hero-stage" ref={stageRef}>
        <div className="hero-stage-glow"></div>
        <div className="hero-panel" ref={panelRef}>
          <div className="panel-chrome">
            <span className="panel-dot r"></span>
            <span className="panel-dot y"></span>
            <span className="panel-dot g"></span>
            <span className="panel-title">project-northstar / live-session.cb</span>
            <span className="panel-pulse">
              <span className="panel-pulse-dot"></span> Live · 4 teams · 02:14:08
            </span>
          </div>

          <div className="panel-body">
            {/* Left rail */}
            <div className="panel-rail">
              <div className="rail-label">Cohort</div>
              <div className="rail-item active"><span className="rail-dot live"></span>Team Alpha</div>
              <div className="rail-item"><span className="rail-dot warn"></span>Team Bravo</div>
              <div className="rail-item"><span className="rail-dot live"></span>Team Charlie</div>
              <div className="rail-item"><span className="rail-dot danger"></span>Team Delta</div>
              <div className="rail-label" style={{ marginTop: 14 }}>Controls</div>
              <div className="rail-item"><span className="rail-dot" style={{ background: 'var(--gold)' }}></span>Inject event</div>
              <div className="rail-item"><span className="rail-dot" style={{ background: 'var(--blue-bright)' }}></span>Advance phase</div>
              <div className="rail-item"><span className="rail-dot" style={{ background: 'var(--muted)' }}></span>Debrief</div>
            </div>

            {/* Main */}
            <div className="panel-main">
              <div className="team-grid">
                <TeamCard name="Team Alpha"   score={scores.a} phase="Phase 4 · Recommendations" trend="up" />
                <TeamCard name="Team Bravo"   score={scores.b} phase="Phase 2 · Discovery" trend="flat" tone="gold" />
                <TeamCard name="Team Charlie" score={scores.c} phase="Phase 3 · Diagnostic" trend="up" />
                <TeamCard name="Team Delta"   score={scores.d} phase="Phase 2 · Behind pace" trend="down" tone="danger" />
              </div>

              <div className="feed">
                <div className="feed-head">
                  <div className="feed-label">Live activity</div>
                  <div className="feed-meta"><span className="live-pip"></span>Streaming · last 60s</div>
                </div>
                {visibleFeed.map((f, i) => (
                  <div className="feed-row" key={`${feedStart}-${i}`}>
                    <div className={`feed-avatar ${f.av}`}>{f.initials}</div>
                    <div className="feed-mid">
                      <div className="feed-from">{f.from} <span>→ {f.target}</span></div>
                      <div className="feed-preview">{f.preview}</div>
                    </div>
                    <div className={`feed-badge ${f.cls}`}>{f.badge}</div>
                  </div>
                ))}
              </div>
            </div>

            {/* Right column */}
            <div className="panel-right">
              <div className="scoring-card">
                <div className="sc-eyebrow">Overall scores · Team Alpha</div>
                <div className="sc-h">Combined - deliverables &amp; comms</div>
                <div className="sc-row">Problem Structuring <span className="sc-grade grade-a">86 / 100</span></div>
                <div className="sc-row">Communication <span className="sc-grade grade-b">74 / 100</span></div>
                <div className="sc-row">Prioritisation <span className="sc-grade grade-a">81 / 100</span></div>
                <div className="sc-row">Stakeholder Mgmt <span className="sc-grade grade-b">78 / 100</span></div>
                <div className="sc-row">Client Satisfaction <span className="sc-grade grade-a">83 / 100</span></div>
              </div>

              <div className="injector">
                <span className="inj-icon">⚡</span>
                <div className="inj-text">
                  <div className="inj-eb">Event injected · 14:32</div>
                  <div className="inj-body">CFO requests an emergency briefing in 20 minutes. Teams must reprioritise.</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function TeamCard({ name, score, phase, trend, tone }) {
  const fillCls = tone === 'gold' ? 'gold' : tone === 'danger' ? 'danger' : '';
  const trendSym = trend === 'up' ? '▲ +2.4' : trend === 'down' ? '▼ -1.8' : '- flat';
  return (
    <div className="team-card">
      <div className="tc-row">
        <div className="tc-name">{name}</div>
        <div className="tc-score">{Math.round(score)}<sup>/100</sup></div>
      </div>
      <div className="tc-bar"><div className={`tc-fill ${fillCls}`} style={{ width: `${score}%` }}></div></div>
      <div className="tc-meta">
        <span><span className="tc-dot"></span>{phase}</span>
        <span className={`tc-trend ${trend}`}>{trendSym}</span>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// CHALLENGE
// ─────────────────────────────────────────────────────────────
function Challenge() {
  const items = [
    { n: '01', h: 'Case studies are passive', p: 'Students read, discuss, present. Nobody practises the actual skill - communicating with real stakeholders, under time pressure, with imperfect information.' },
    { n: '02', h: 'Role-plays don\'t scale',  p: 'A facilitator can play one character. Project Northstar runs twelve AI-powered stakeholders simultaneously across four or more teams in a single room.' },
    { n: '03', h: 'Assessment lacks rigour',  p: 'Faculty assess on feel, not evidence. There is no consistent standard, no audit trail, and nothing for students to learn from after the room empties.' },
  ];
  const [headRef, headSeen] = useInView({ threshold: 0.3 });
  return (
    <section className="section challenge" id="problem">
      <div className="container">
        <div className="challenge-head">
          <div className="section-eyebrow">The Challenge · 001</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            Why traditional teaching <em>falls short.</em>
          </h2>
          <p className="section-lead">
            Three structural gaps separate classroom learning from how consulting is actually practised. The simulation closes all three - in a single workshop.
          </p>
        </div>
        <div className="challenge-grid">
          {items.map((it, i) => <ChallengeCard key={i} {...it} idx={i} />)}
        </div>
      </div>
    </section>
  );
}

function ChallengeCard({ n, h, p, idx }) {
  const [ref, seen] = useInView({ threshold: 0.25 });
  return (
    <div ref={ref} className="challenge-card fade-up" style={{ transitionDelay: `${idx * 100}ms` }}>
      <div className={`fade-up ${seen ? 'in' : ''}`} style={{ display: 'contents' }}>
        <div className="cc-num">{n}</div>
        <h3>{h}</h3>
        <p>{p}</p>
      </div>
    </div>
  );
}

// Wrap each card properly - recompute the fade
function ChallengeCardV2({ n, h, p, idx }) {
  const [ref, seen] = useInView({ threshold: 0.2 });
  return (
    <div ref={ref} className={`challenge-card fade-up ${seen ? 'in' : ''}`} style={{ transitionDelay: `${idx * 100}ms` }}>
      <div className="cc-num">{n}</div>
      <h3>{h}</h3>
      <p>{p}</p>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// HOW IT WORKS - pinned horizontal scroll
// ─────────────────────────────────────────────────────────────
const PHASES = [
  {
    id: 'P1', roman: 'i.', title: 'Briefing',
    desc: 'Teams receive the Project Charter - background, stakeholders, prior work, market assessment and current situation. Their first deliverable: a structured Problem Statement Worksheet that locks down the decision question before a single conversation begins.',
    duration: '30 min', deliverable: 'Problem Statement Worksheet',
  },
  {
    id: 'P2', roman: 'ii.', title: 'Discovery',
    desc: 'Engage AI stakeholders, gather information on the business\u2019s financial position, and build initial hypotheses to recover lost margin. The output is a comprehensive in-sim Hypothesis Pack covering sizing, rationale and initial path to capture.',
    duration: '60 min', deliverable: 'Hypothesis Pack',
  },
  {
    id: 'P3', roman: 'iii.', title: 'Diagnostic',
    desc: 'Pressure-test the priority hypothesis. Pull more information from the right stakeholders, run the data analysis, isolate the minutiae driving the issue. The deliverable is an in-depth, in-sim document on the primary lever.',
    duration: '60 min', deliverable: 'Diagnostic Findings',
  },
  {
    id: 'P4', roman: 'iv.', title: 'Recommendations',
    desc: 'Craft the implementation detail on the chosen lever - what the client should do to recover margin, how it sizes (£m and pp), and the realistic path to capture. The output is a tight, decision-grade Recommendations Brief.',
    duration: '50 min', deliverable: 'Recommendations Brief',
  },
  {
    id: 'P5', roman: 'v.', title: 'SteerCo',
    desc: 'Ninety minutes to build the full Steering Committee document, then individual presentations to a board of faculty and university staff. The simulation\u2019s grading rubric runs alongside the live debate.',
    duration: '90 min', deliverable: 'SteerCo Document',
  },
];

function HowItWorks() {
  const [active, setActive] = useState(0);
  const [headRef, headSeen] = useInView({ threshold: 0.3 });
  const ph = PHASES[active];

  return (
    <section className="section how-static" id="how">
      <div className="container">
        <div className="section-head">
          <div className="section-eyebrow">How It Works · 002</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            Move beyond the case study.<br/><em>Run the engagement.</em>
          </h2>
          <p className="section-lead how-lead">
            Each workshop mirrors a compressed consulting engagement - from brief to board. Students navigate ambiguity, manage difficult stakeholders, and defend evidence-based recommendations in front of a live SteerCo.
          </p>
        </div>

        <div className="how-static-grid">
          <div className="how-static-tabs" role="tablist" aria-label="Engagement phases">
            {PHASES.map((p, i) => (
              <button
                key={p.id}
                role="tab"
                aria-selected={i === active}
                className={`how-tab ${i === active ? 'active' : ''}`}
                onClick={() => setActive(i)}
              >
                <span className="how-tab-num">{String(i + 1).padStart(2, '0')}</span>
                <span className="how-tab-mid">
                  <span className="how-tab-title">{p.title}</span>
                  <span className="how-tab-meta">{p.duration} · {p.deliverable}</span>
                </span>
                <span className="how-tab-arrow" aria-hidden="true">→</span>
              </button>
            ))}
          </div>

          <div className="how-static-detail" key={active}>
            <PhaseCard ph={ph} idx={active} active={true} />
          </div>
        </div>
      </div>
    </section>
  );
}

function PhaseCard({ ph, idx, active }) {
  return (
    <div className={`phase-card ${active ? 'active' : ''}`}>
      <div className="phase-text">
        <div className="phase-id">Phase {ph.id} · {String(idx + 1).padStart(2,'0')}</div>
        <h3 className="phase-title">{ph.title}</h3>
        <div className="phase-roman">{ph.roman}</div>
        <p className="phase-desc">{ph.desc}</p>
        <div className="phase-meta">
          <div className="phase-meta-cell">
            <div className="pmc-label">Duration</div>
            <div className="pmc-value">{ph.duration}</div>
          </div>
          <div className="phase-meta-cell">
            <div className="pmc-label">Output</div>
            <div className="pmc-value">{ph.deliverable}</div>
          </div>
        </div>
      </div>
      <div className="phase-mock">
        {idx === 0 && <MockBriefing active={active} />}
        {idx === 1 && <MockDiscovery active={active} />}
        {idx === 2 && <MockDiagnostic active={active} />}
        {idx === 3 && <MockRecommend active={active} />}
        {idx === 4 && <MockSteerCo active={active} />}
      </div>
    </div>
  );
}

function MockBriefing() {
  return (
    <div className="mock-memo">
      <div className="memo-header">
        <div className="memo-title">
          Project Northstar
          <sub>Problem Statement Worksheet · v0.1</sub>
        </div>
        <div className="memo-stamp">Day 0 · 09:00</div>
      </div>
      <div className="memo-section">
        <div className="memo-eb">Decision question</div>
        <div className="memo-line long"></div>
        <div className="memo-line mid"></div>
      </div>
      <div className="memo-section">
        <div className="memo-eb">Context · success criteria</div>
        <div className="memo-line long"></div>
        <div className="memo-line short"></div>
      </div>
      <div className="memo-section">
        <div className="memo-eb">Scope · boundaries</div>
        <div className="memo-line mid"></div>
        <div className="memo-line short"></div>
      </div>
      <div className="memo-section">
        <div className="memo-eb">Key stakeholders</div>
        <div className="memo-stakeholders">
          <div className="mst" style={{ background: 'linear-gradient(135deg, #0079cf, #002d6e)' }}>DM</div>
          <div className="mst" style={{ background: 'linear-gradient(135deg, #0097a7, #004d56)' }}>SL</div>
          <div className="mst" style={{ background: 'linear-gradient(135deg, #b8860b, #5c4300)' }}>RV</div>
          <div className="mst" style={{ background: 'linear-gradient(135deg, #7d4f9e, #2a1843)' }}>KP</div>
          <div className="mst" style={{ background: 'linear-gradient(135deg, #4d5e7c, #1e2a40)' }}>+8</div>
        </div>
      </div>
    </div>
  );
}

function MockDiscovery({ active }) {
  const [showUnlock, setShowUnlock] = useState(false);
  useEffect(() => {
    if (!active) { setShowUnlock(false); return; }
    const id = setTimeout(() => setShowUnlock(true), 900);
    return () => clearTimeout(id);
  }, [active]);
  return (
    <div className="mock-convo">
      <div className="convo-msg">
        <div className="feed-avatar teal" style={{ width: 28, height: 28 }}>SL</div>
        <div className="convo-text">
          <strong>Sarah Liu · CFO</strong>
          We don't share the financial model unless you can tell me precisely what you need it for. Be specific.
          <div className="convo-meta">↳ Stakeholder rapport · 0.62</div>
        </div>
      </div>
      <div className="convo-msg user">
        <div className="convo-text">
          <strong>Team Alpha</strong>
          We need FY20-FY24 P&amp;L and segment splits to test our margin compression hypothesis - specifically Advisory Fees decline vs. Personnel growth.
          <div className="convo-meta">↳ Quality score · A- · +6 rapport</div>
        </div>
      </div>
      {showUnlock && (
        <div className="data-unlock">
          <div className="unlock-icon">⬡</div>
          <div className="unlock-text">
            Northbridge_Financial_Model_v3.xlsx
            <sub>Unlocked · 2 of 6 documents</sub>
          </div>
        </div>
      )}
    </div>
  );
}

function MockDiagnostic({ active }) {
  const bars = [
    { v: 118, x: 'FY20', h: 56 },
    { v: 136, x: 'FY21', h: 68 },
    { v: 142, x: 'FY22', h: 72 },
    { v: 137, x: 'FY23', h: 70, gold: true },
    { v: 115, x: 'FY24', h: 52 },
  ];
  return (
    <div className="mock-data">
      <div className="diag-tabs">
        <div className="diag-tab active">Revenue</div>
        <div className="diag-tab">Margin</div>
        <div className="diag-tab">Segments</div>
        <div className="diag-tab">Cost base</div>
      </div>
      <div className="diag-chart">
        <div className="chart-axes">£m</div>
        <div className="chart-bars">
          {bars.map((b, i) => (
            <div key={i} className={`chart-bar ${b.gold ? 'gold' : ''}`} data-v={b.v}
                 style={{ height: active ? `${b.h}%` : '0%', transitionDelay: `${i * 80}ms` }}/>
          ))}
        </div>
        <div className="chart-x">
          {bars.map((b, i) => <span key={i}>{b.x}</span>)}
        </div>
        <div className="diag-callout">-16% YoY · root cause TBD</div>
      </div>
    </div>
  );
}

function MockRecommend({ active }) {
  const milestones = [
    { q: 'Wk 0-2',  l: 'Pilot scope' },
    { q: 'Wk 2-6',  l: 'Tier rollout' },
    { q: 'Wk 6-14', l: 'Scale & enable' },
    { q: 'Wk 14+',  l: 'Run-rate BAU' },
  ];
  return (
    <div className="mock-rec">
      <div className="rec-head">
        <div className="rec-tag">Lever 03 · Recommendation Brief</div>
        <div className="rec-lever">Re-segment advisory tier 2.<em> Reprice to value, not headcount.</em></div>
      </div>

      <div className="rec-sizing">
        <div className="rec-tile">
          <div className="rec-tile-label">Margin recovery</div>
          <div className="rec-tile-value" style={{ opacity: active ? 1 : 0, transitionDelay: '120ms' }}>
            +£14.2<sub>m</sub>
          </div>
          <div className="rec-tile-foot">y2 run-rate</div>
        </div>
        <div className="rec-tile gold">
          <div className="rec-tile-label">EBITDA pp lift</div>
          <div className="rec-tile-value" style={{ opacity: active ? 1 : 0, transitionDelay: '240ms' }}>
            +6.4<sub>pp</sub>
          </div>
          <div className="rec-tile-foot">vs. FY24 baseline</div>
        </div>
      </div>

      <div className="rec-roadmap">
        <div className="rec-roadmap-label">Path to capture</div>
        <div className="rec-roadmap-track">
          <div className="rec-roadmap-line">
            <div
              className="rec-roadmap-fill"
              style={{ width: active ? '70%' : '0%', transitionDelay: '360ms' }}
            />
          </div>
          <div className="rec-roadmap-pins">
            {milestones.map((m, i) => (
              <div key={i} className={`rec-pin ${i < 3 ? 'done' : ''}`}>
                <span className="rec-pin-dot" />
                <span className="rec-pin-q">{m.q}</span>
                <span className="rec-pin-l">{m.l}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="rec-foot">
        <span className="rec-foot-label">Confidence</span>
        <span className="rec-foot-bar">
          <span className="rec-foot-fill" style={{ width: active ? '78%' : '0%', transitionDelay: '500ms' }} />
        </span>
        <span className="rec-foot-val">High · evidence in §3</span>
      </div>
    </div>
  );
}

function MockSteerCo() {
  return (
    <div className="mock-steerco">
      <div className="steerco-screen">
        <div className="sc-h-row">
          <div className="sc-presentation-title">
            Northbridge: A path back to growth
            <sub>SteerCo · slide 04 / 12</sub>
          </div>
          <div className="sc-page">14:42:08</div>
        </div>
        <div className="sc-content">
          <div className="sc-panel">
            <strong>Diagnosis</strong>
            EBITDA margin contracted from <em>40.4%</em> to <em>17.2%</em> over four years - driven by personnel growth outpacing revenue.
            <span className="stat">-23.2<em>pp</em></span>
          </div>
          <div className="sc-panel">
            <strong>Recommendation</strong>
            Three-pillar plan: rationalise advisory bench, re-price transaction fees, exit two segments.
            <span className="stat">+£18<em>m</em></span>
          </div>
        </div>
        <div className="sc-bottombar">
          <span>Northstar Board · 5 stakeholders present</span>
          <span className="sc-live">Live grading</span>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// FACULTY
// ─────────────────────────────────────────────────────────────
function Faculty() {
  const [scores, setScores] = useState({ a: 88, b: 61, c: 74, d: 42 });
  const [eventVisible, setEventVisible] = useState(true);
  const [eventIdx, setEventIdx] = useState(0);

  const events = [
    { eb: 'Event injected · 14:32', body: 'CFO requests an emergency briefing in 20 minutes. Teams must reprioritise.' },
    { eb: 'Event injected · 14:48', body: 'Board wants preliminary findings - 15 minutes notice. Pressure-test the framing.' },
    { eb: 'Event injected · 15:04', body: 'Activist investor leaks to FT. Communications strategy needs to shift before close.' },
  ];

  useEffect(() => {
    const id = setInterval(() => {
      setScores((s) => ({
        a: Math.max(72, Math.min(94, s.a + (Math.random() * 4 - 2))),
        b: Math.max(50, Math.min(72, s.b + (Math.random() * 5 - 2.5))),
        c: Math.max(62, Math.min(82, s.c + (Math.random() * 4 - 2))),
        d: Math.max(34, Math.min(54, s.d + (Math.random() * 6 - 2))),
      }));
    }, 2400);
    return () => clearInterval(id);
  }, []);

  useEffect(() => {
    const id = setInterval(() => {
      setEventVisible(false);
      setTimeout(() => {
        setEventIdx((i) => (i + 1) % events.length);
        setEventVisible(true);
      }, 600);
    }, 7000);
    return () => clearInterval(id);
  }, []);

  const [headRef, headSeen] = useInView({ threshold: 0.3 });

  return (
    <section className="section faculty" id="faculty">
      <div className="container">
        <div className="section-head">
          <div className="section-eyebrow">The Facilitator · 003</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            We run the room.<br/>You focus on <em>learning&nbsp;outcomes.</em>
          </h2>
        </div>
        <div className="faculty-grid">
          <div>
            <p className="section-lead">
              Every workshop is delivered end-to-end by former MBB consultants. Briefing, facilitation, in-room coaching, and structured written feedback. Nothing for your faculty to prepare or grade.
            </p>
            <ul className="faculty-list">
              <li><span className="fl-id">01</span><div><strong>Real-time visibility</strong>Every team's progress, scores, stakeholder rapport, and unlocks visible in one dashboard.</div></li>
              <li><span className="fl-id">02</span><div><strong>Phase gate control</strong>Teams advance when ready - not on a timer. Pace adapts to the cohort.</div></li>
              <li><span className="fl-id">03</span><div><strong>Live event injection</strong>Test adaptability under pressure. CFO briefings, board demands, activist letters - when you decide.</div></li>
              <li><span className="fl-id">04</span><div><strong>Structured debrief</strong>Per-team reports with examiner commentary against an MBB-grade rubric, delivered within minutes of the SteerCo.</div></li>
              <li><span className="fl-id">05</span><div><strong>MBB-level training built in</strong>Every workshop reinforces consulting fundamentals - hypothesis-driven thinking, MECE structure, issue-tree decomposition, the pyramid principle, and quantification under pressure.</div></li>
            </ul>
          </div>

          {/* Live faculty panel */}
          <FacultyPanel scores={scores} event={events[eventIdx]} eventVisible={eventVisible} />
        </div>
      </div>
    </section>
  );
}

function FacultyPanel({ scores, event, eventVisible }) {
  const [tab, setTab] = useState('scores');
  return (
    <div className="fac-panel">
      <div className="panel-chrome">
        <span className="panel-dot r"></span>
        <span className="panel-dot y"></span>
        <span className="panel-dot g"></span>
        <span className="panel-title">facilitator-console</span>
        <div className="fac-panel-tabs">
          <div className={`fac-tab ${tab === 'scores' ? 'active' : ''}`} onClick={() => setTab('scores')}>Scores</div>
          <div className={`fac-tab ${tab === 'rubric' ? 'active' : ''}`} onClick={() => setTab('rubric')}>Rubric</div>
          <div className={`fac-tab ${tab === 'debrief' ? 'active' : ''}`} onClick={() => setTab('debrief')}>Debrief</div>
        </div>
      </div>

      {tab === 'scores' && (
        <div className="fac-body">
          <div className="mini-grid">
            <MiniCard name="Team Alpha"   score={scores.a} phase="Phase 4 · Recommendations" />
            <MiniCard name="Team Bravo"   score={scores.b} phase="Phase 2 · Discovery" tone="gold" />
            <MiniCard name="Team Charlie" score={scores.c} phase="Phase 3 · Diagnostic" />
            <MiniCard name="Team Delta"   score={scores.d} phase="Phase 2 · Behind" tone="danger" />
          </div>

          <div className="event-card" style={{
            opacity: eventVisible ? 1 : 0,
            transform: eventVisible ? 'none' : 'translateY(-6px)',
            transition: 'opacity 0.4s, transform 0.4s'
          }}>
            <span className="inj-icon">⚡</span>
            <div className="inj-text">
              <div className="inj-eb">{event.eb}</div>
              <div className="inj-body">{event.body}</div>
            </div>
          </div>

          <div className="fac-ctrls">
            <div className="fac-btn">⚡ Inject event</div>
            <div className="fac-btn primary">▶ Advance phase</div>
            <div className="fac-btn">⬡ Debrief</div>
          </div>
        </div>
      )}

      {tab === 'rubric' && (
        <div className="fac-body">
          <div className="scoring-card rubric-card" style={{ padding: 16 }}>
            <div className="sc-eyebrow">Communications grading - email</div>
            <div className="sc-h" style={{ marginBottom: 10 }}>Team Alpha - last reply</div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.05s' }}>Hypothesis-led thinking <span className="sc-grade grade-a">82 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.12s' }}>Synthesis before asking <span className="sc-grade grade-b">71 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.19s' }}>Structural clarity <span className="sc-grade grade-a">88 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.26s' }}>Stakeholder awareness <span className="sc-grade grade-b">76 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.33s' }}>Action orientation <span className="sc-grade grade-a">84 / 100</span></div>
          </div>
          <div className="scoring-card rubric-card" style={{ padding: 16 }}>
            <div className="sc-eyebrow">Overall scores - cumulative</div>
            <div className="sc-h" style={{ marginBottom: 10 }}>Deliverables &amp; comms combined</div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.42s' }}>Problem Structuring <span className="sc-grade grade-a">86 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.49s' }}>Communication <span className="sc-grade grade-b">74 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.56s' }}>Prioritisation <span className="sc-grade grade-a">81 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.63s' }}>Stakeholder Mgmt <span className="sc-grade grade-b">78 / 100</span></div>
            <div className="sc-row rubric-row" style={{ animationDelay: '0.70s' }}>Client Satisfaction <span className="sc-grade grade-a">83 / 100</span></div>
            <div className="sc-row rubric-row rubric-overall" style={{ animationDelay: '0.80s' }}>
              <strong>OVERALL</strong>
              <span className="sc-grade grade-a">82 / 100</span>
            </div>
          </div>
        </div>
      )}

      {tab === 'debrief' && (
        <div className="fac-body">
          <div className="injector" style={{ background: 'rgba(0,109,188,0.08)', borderColor: 'rgba(0,109,188,0.3)' }}>
            <span className="inj-icon" style={{ color: 'var(--blue-bright)' }}>⬡</span>
            <div className="inj-text">
              <div className="inj-eb" style={{ color: 'var(--blue-bright)' }}>Auto-generated · 14:51</div>
              <div className="inj-body">Per-team debrief reports for all 4 teams - examiner commentary, score breakdowns, transcript highlights, learning recommendations.</div>
            </div>
          </div>
          {['Team Alpha - 82 / 100','Team Bravo - 64 / 100','Team Charlie - 76 / 100','Team Delta - 48 / 100'].map((t,i)=>(
            <div key={i} style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              padding: '12px 14px', borderRadius: 8,
              background: 'rgba(0, 25, 60, 0.3)', border: '1px solid var(--border)',
              fontSize: 13, color: 'rgba(255,255,255,0.78)', fontWeight: 400, fontFamily: 'var(--sans)'
            }}>
              <span>{t}</span>
              <span style={{ fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--gold)', letterSpacing: '0.12em' }}>↓ DOWNLOAD</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function MiniCard({ name, score, phase, tone }) {
  const cls = tone === 'gold' ? 'gold' : tone === 'danger' ? 'danger' : '';
  return (
    <div className="mini-card">
      <div className="mini-top">
        <div className="mini-name">{name}</div>
        <div className="mini-score">{Math.round(score)}<sub>/100</sub></div>
      </div>
      <div className="mini-bar">
        <div className={`mini-fill ${cls}`} style={{ width: `${score}%` }}></div>
      </div>
      <div className="mini-phase">{phase}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// STUDENTS
// ─────────────────────────────────────────────────────────────
function Students() {
  const initial = [
    { id: 1, av: 'blue', initials: 'KP', from: 'Kevin Park', role: 'Head of Operations', preview: 'Re: Data quality concerns you raised...', badge: '+8', cls: 'badge-pos', t: 'now', unread: false },
    { id: 2, av: 'teal', initials: 'SL', from: 'Sarah Liu',  role: 'CFO',                preview: 'The margin analysis you sent lacks a clear so-what...', badge: '-4', cls: 'badge-neg', t: '2m', unread: false },
    { id: 3, av: 'gold', initials: 'RV', from: 'Richard Vance', role: 'Partner',         preview: 'Well-structured - but consider leading with...', badge: 'Coach', cls: 'badge-coach', t: '4m', unread: false },
  ];
  const newOnes = [
    { id: 4, av: 'plum', initials: 'DM', from: 'David Marsh', role: 'CEO',     preview: 'Impressive framing on the cost analysis. Can you expand the segment view?', badge: '+12', cls: 'badge-pos', t: 'just now', unread: true },
    { id: 5, av: 'blue', initials: 'KP', from: 'Kevin Park', role: 'Head of Ops', preview: 'Pulling the FY24 forecast - when do you need it for the SteerCo?', badge: '+3', cls: 'badge-pos', t: 'just now', unread: true },
  ];

  const [rows, setRows] = useState(initial);
  const [step, setStep] = useState(0);
  useEffect(() => {
    const id = setInterval(() => {
      setStep((s) => {
        const next = s + 1;
        if (next > newOnes.length) {
          setRows(initial);
          return 0;
        }
        setRows([...initial, ...newOnes.slice(0, next)]);
        return next;
      });
    }, 4500);
    return () => clearInterval(id);
  }, []);

  const [statsRef, statsSeen] = useInView({ threshold: 0.3 });
  const c1 = useCountUp(12, 1400, statsSeen);
  const c2 = useCountUp(6,  1200, statsSeen);
  const c3 = useCountUp(5,  1000, statsSeen);
  const c4 = useCountUp('∞', 0,    statsSeen);

  const [headRef, headSeen] = useInView({ threshold: 0.3 });

  return (
    <section className="section students" id="students">
      <div className="container">
        <div className="section-head">
          <div className="section-eyebrow">The Students · 004</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            Live practice. Real stakes.<br/><em>Immediate&nbsp;feedback.</em>
          </h2>
        </div>
        <div className="students-grid">
          {/* Inbox panel */}
          <div className="inbox-panel">
            <div className="panel-chrome">
              <span className="panel-dot r"></span>
              <span className="panel-dot y"></span>
              <span className="panel-dot g"></span>
              <span className="panel-title">team-alpha / inbox</span>
              <span className="panel-pulse"><span className="panel-pulse-dot"></span>{rows.filter(r=>r.unread).length} new</span>
            </div>
            <div className="inbox-body">
              {rows.map((r, i) => (
                <div key={r.id} className={`inbox-row ${r.unread ? 'unread' : ''}`} style={{ animationDelay: `${i < initial.length ? i * 0.15 : 0}s` }}>
                  <div className={`feed-avatar ${r.av}`} style={{ width: 30, height: 30, fontSize: 10 }}>{r.initials}</div>
                  <div className="inbox-mid">
                    <div className="inbox-from">{r.from} <span>· {r.role}</span></div>
                    <div className="inbox-preview">{r.preview}</div>
                  </div>
                  <div className={`feed-badge ${r.cls}`}>{r.badge}</div>
                  <div className="inbox-time">{r.t}</div>
                </div>
              ))}
            </div>
            <div className="composer">
              <span>Drafting reply to Kevin Park…</span>
              <span className="typing-dots"><span></span><span></span><span></span></span>
            </div>
          </div>

          <div>
            <p className="section-lead">
              Students manage a live inbox, interview AI-powered characters, and unlock data through the quality of their communication.<br/><br/>
              They build MBB-style models to size the issue, pressure-test assumptions, and quantify the recommendation - then defend it to a virtual boardroom, coached the whole way through by experienced consultants.
            </p>
            <div className="stu-stats" ref={statsRef}>
              <div className="stat-cell">
                <div className="stat-num">{c1}</div>
                <div className="stat-lbl">AI-powered stakeholders, each with a distinct personality and agenda</div>
              </div>
              <div className="stat-cell">
                <div className="stat-num">{c2}</div>
                <div className="stat-lbl">Unlockable data documents, earned through quality communication</div>
              </div>
              <div className="stat-cell">
                <div className="stat-num">{c3}</div>
                <div className="stat-lbl">Structured deliverables, graded by experienced former MBB consultants, and an AI-enabled MBB-matrix</div>
              </div>
              <div className="stat-cell">
                <div className="stat-num"><em>{c4}</em></div>
                <div className="stat-lbl">Real-time coaching, after every stakeholder message</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// PRICING
// ─────────────────────────────────────────────────────────────
function Pricing() {
  const tiers = [
    {
      tier: 'Pilot', name: 'Single Workshop',
      desc: 'One workshop for up to five teams, fully facilitated. Pre-workshop briefing, live delivery, and structured per-team debrief reports.',
      feats: [
        'Up to 5 concurrent teams and 30 students',
        'Full facilitation by a former MBB consultant',
        'Pre-workshop programme director briefing',
        'Per-team debrief reports within 24h',
      ],
    },
    {
      tier: 'Programme', name: 'Multi-Cohort', featured: true,
      desc: 'Multiple workshops across a term or academic year, with scenario difficulty tailored per cohort. Aggregated learning-outcomes reporting.',
      feats: [
        'Multiple workshops per academic year',
        'Cross-cohort and cross-programme delivery',
        'Difficulty calibrated per cohort and stage',
        'Aggregated learning-outcomes reporting',
        'Annual account relationship',
      ],
    },
    {
      tier: 'Enterprise', name: 'Custom Build',
      desc: 'Bespoke scenario designed around your industry or institutional brand. White-labelled environment and facilitator certification.',
      feats: [
        'Custom scenario development',
        'White-labelled, branded environment',
        'Facilitator training and certification',
        'LMS integration available',
        'Dedicated ongoing account support',
      ],
    },
  ];
  const [headRef, headSeen] = useInView({ threshold: 0.3 });

  return (
    <section className="section pricing" id="pricing">
      <div className="container">
        <div className="pricing-head">
          <div className="section-eyebrow">Engagement Model · 005</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            Built around <em>your institution.</em>
          </h2>
          <p>Every engagement is scoped to your cohort size, academic calendar, and learning objectives. Pricing is agreed per institution - never per seat.</p>
        </div>
        <div className="price-grid">
          {tiers.map((t, i) => (
            <div key={i} className={`price-card ${t.featured ? 'featured' : ''}`}>
              <div className="price-tier">{t.tier}</div>
              <h3>{t.name}</h3>
              <p>{t.desc}</p>
              <ul className="price-feats">
                {t.feats.map((f, j) => <li key={j}>{f}</li>)}
              </ul>
            </div>
          ))}
        </div>
        <div className="pricing-cta">
          <p>All pricing is agreed per institution</p>
          <a href="#contact" className="btn-primary">
            Book a 30-Minute Walkthrough
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 7h8m0 0L7.5 3.5M11 7l-3.5 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </a>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// BOOK A DEMO
// ─────────────────────────────────────────────────────────────
function Book() {
  const [submitted, setSubmitted] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const [headRef, headSeen] = useInView({ threshold: 0.3 });

  const onSubmit = async (e) => {
    e.preventDefault();
    if (submitting) return;
    setError(null);
    setSubmitting(true);
    const form = e.currentTarget;
    const data = new FormData(form);
    try {
      const res = await fetch('https://formspree.io/f/xjgprooy', {
        method: 'POST',
        body: data,
        headers: { 'Accept': 'application/json' },
      });
      if (res.ok) {
        setSubmitted(true);
        form.reset();
      } else {
        const json = await res.json().catch(() => ({}));
        const msg = json && json.errors && json.errors.length
          ? json.errors.map(er => er.message).join(', ')
          : 'Submission failed. Please try again or email hello@consultingblueprint.co.uk.';
        setError(msg);
      }
    } catch (err) {
      setError('Network error. Please check your connection and try again, or email hello@consultingblueprint.co.uk.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <section className="section book" id="contact">
      <div className="container">
        <div className="section-head">
          <div className="section-eyebrow">Book a Demo · 006</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            Thirty minutes.<br/>See <em>the&nbsp;full&nbsp;simulation.</em>
          </h2>
        </div>
        <div className="book-grid">
          <div>
            <p className="section-lead">
              We'll walk you through a live Project Northstar session, show you the facilitator console, and discuss how to scope an engagement that fits your cohort and calendar.
            </p>
            <div className="book-anchors">
              <div className="book-anchor">
                <div className="ba-num">01</div>
                <div>
                  <strong>Move beyond passive learning</strong>
                  <span>Students practise real consulting skills - they don't just discuss them.</span>
                </div>
              </div>
              <div className="book-anchor">
                <div className="ba-num">02</div>
                <div>
                  <strong>Scale what role-plays can't</strong>
                  <span>Twelve AI stakeholders, four or more teams, fully delivered by experienced consultants.</span>
                </div>
              </div>
              <div className="book-anchor">
                <div className="ba-num">03</div>
                <div>
                  <strong>Assess with rigour</strong>
                  <span>Every deliverable scored against an MBB-grade matrix. Debrief with data - never anecdotes.</span>
                </div>
              </div>
            </div>
          </div>

          <form className="book-form" onSubmit={onSubmit}>
            {!submitted ? (
              <>
                <div className="form-row">
                  <div className="form-field">
                    <label className="form-label" htmlFor="bf-name">Your Name</label>
                    <input id="bf-name" name="name" type="text" className="form-input" placeholder="Prof. Jane Smith" required disabled={submitting}/>
                  </div>
                  <div className="form-field">
                    <label className="form-label" htmlFor="bf-role">Role</label>
                    <input id="bf-role" name="role" type="text" className="form-input" placeholder="Programme Director" required disabled={submitting}/>
                  </div>
                </div>
                <div className="form-row full">
                  <div className="form-field">
                    <label className="form-label" htmlFor="bf-institution">Institution</label>
                    <input id="bf-institution" name="institution" type="text" className="form-input" placeholder="London Business School" required disabled={submitting}/>
                  </div>
                </div>
                <div className="form-row full">
                  <div className="form-field">
                    <label className="form-label" htmlFor="bf-email">Work Email</label>
                    <input id="bf-email" name="email" type="email" className="form-input" placeholder="j.smith@lbs.ac.uk" required disabled={submitting}/>
                  </div>
                </div>
                <div className="form-row full">
                  <div className="form-field">
                    <label className="form-label" htmlFor="bf-cohort">Tell us about your cohort</label>
                    <textarea id="bf-cohort" name="cohort" className="form-input" placeholder="e.g. Full-time MBA, ~120 students, looking to embed consulting skills in Term 2…" disabled={submitting}></textarea>
                  </div>
                </div>
                {/* Honeypot - hidden from real users, bots fill it in */}
                <input type="text" name="_gotcha" tabIndex="-1" autoComplete="off" style={{ position: 'absolute', left: '-9999px', width: 1, height: 1, opacity: 0 }} aria-hidden="true"/>
                {/* Email subject + reply-to hints for the inbox */}
                <input type="hidden" name="_subject" value="New demo request - Consulting Blueprint"/>
                {error && (
                  <div className="form-error" role="alert">{error}</div>
                )}
                <button type="submit" className="form-submit" disabled={submitting}>
                  {submitting ? 'Sending…' : 'Request a Demo'}
                  {!submitting && (
                    <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 7h8m0 0L7.5 3.5M11 7l-3.5 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
                  )}
                </button>
              </>
            ) : (
              <div style={{
                padding: '60px 20px', textAlign: 'center', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center'
              }}>
                <div style={{
                  width: 56, height: 56, borderRadius: '50%',
                  background: 'rgba(34,201,122,0.12)',
                  border: '1px solid rgba(34,201,122,0.4)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center'
                }}>
                  <svg width="22" height="22" viewBox="0 0 16 16" fill="none"><path d="M3 8l3 3 7-7" stroke="#22c97a" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
                </div>
                <div style={{ fontFamily: 'var(--serif)', fontSize: 24, fontWeight: 600 }}>Request received.</div>
                <div style={{ fontSize: 14, color: 'rgba(255,255,255,0.6)', maxWidth: 380, lineHeight: 1.6, fontWeight: 300 }}>
                  We'll be in touch within 24 hours to schedule your live walkthrough of Project Northstar.
                </div>
              </div>
            )}
          </form>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// FOOTER
// ─────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer>
      <div className="container">
        <div className="footer-grid">
          <div className="footer-brand">
            <h3>Consulting <em>Blueprint</em></h3>
            <p>Built by Jake Ardley - former McKinsey Engagement Manager and British Army Officer.<br/><br/>
              Jake has first-hand experience at junior and mid-level in MBB, and holds an MBA from a top business school.<br/><br/>
              He learned the traditional way - case studies, frameworks, and role-plays.<br/><br/>
              The simulator exists because he knows exactly what that misses: real pressure, real ambiguity, real stakeholders who push back.</p>
          </div>
          <div className="footer-col">
            <h4>Product</h4>
            <ul>
              <li><a href="#how"><span className="col-tag">/01</span>How it works</a></li>
              <li><a href="#faculty"><span className="col-tag">/02</span>The facilitator</a></li>
              <li><a href="#students"><span className="col-tag">/03</span>The students</a></li>
              <li><a href="#pricing"><span className="col-tag">/04</span>Pricing</a></li>
            </ul>
          </div>
          <div className="footer-col">
            <h4>Get in touch</h4>
            <ul>
              <li><a href="mailto:hello@jakeardley.uk"><span className="col-tag">Email</span>hello@jakeardley.uk</a></li>
              <li><a href="https://www.linkedin.com/in/jakeardley" target="_blank" rel="noopener noreferrer"><span className="col-tag">LinkedIn</span>Jake Ardley</a></li>
              <li><a href="#contact"><span className="col-tag">Demo</span>Book a walkthrough</a></li>
            </ul>
          </div>
        </div>
        <div className="footer-bottom">
          <p>© 2026 Jake Ardley Limited. All rights reserved. Jake Ardley Limited, trading as Jake Ardley and Consulting Blueprint, is a private limited company registered in England and Wales (No. 16910845). Registered office: 3 Topiary Square, Richmond, TW9 2DB.</p>
        </div>
      </div>
    </footer>
  );
}

// ─────────────────────────────────────────────────────────────
// PAGE - global scroll handlers (nav, progress rail)
// ─────────────────────────────────────────────────────────────
function Page() {
  useEffect(() => {
    const nav = document.getElementById('nav');
    const rail = document.getElementById('rail');
    const railPhase = document.getElementById('rail-phase');
    const railPct = document.getElementById('rail-pct');

    const phases = [
      { name: 'The Challenge',     from: 0.00 },
      { name: 'How It Works',      from: 0.18 },
      { name: 'The Facilitator',   from: 0.40 },
      { name: 'The Students',      from: 0.58 },
      { name: 'Engagement Model',  from: 0.74 },
      { name: 'Book a Demo',       from: 0.88 },
    ];

    const onScroll = () => {
      const y = window.scrollY;
      if (nav) nav.classList.toggle('scrolled', y > 30);
      if (rail) rail.classList.toggle('show', y > 220);

      const docH = document.documentElement.scrollHeight - window.innerHeight;
      const pct = docH > 0 ? Math.min(1, Math.max(0, y / docH)) : 0;
      if (rail) rail.style.setProperty('--scroll-pct', `${pct * 100}%`);
      if (railPct) railPct.textContent = String(Math.round(pct * 100)).padStart(2,'0') + '%';

      const cur = phases.slice().reverse().find((p) => pct >= p.from) || phases[0];
      if (railPhase) {
        railPhase.innerHTML = `<em>${cur.name}</em>`;
      }
    };

    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  // Smooth-scroll for in-page anchor links
  useEffect(() => {
    const handler = (e) => {
      const a = e.target.closest && e.target.closest('a[href^="#"]');
      if (!a) return;
      const href = a.getAttribute('href');
      if (!href || href === '#') return;
      const t = document.querySelector(href);
      if (!t) return;
      e.preventDefault();
      t.scrollIntoView({ behavior: 'smooth', block: 'start' });
    };
    document.addEventListener('click', handler);
    return () => document.removeEventListener('click', handler);
  }, []);

  return (
    <>
      <Hero />
      <Challenge />
      <HowItWorks />
      <Faculty />
      <Students />
      <Pricing />
      <Book />
      <Footer />
    </>
  );
}

// Switch the broken ChallengeCard usage
const _orig = Challenge;
// eslint-disable-next-line no-func-assign
function ChallengeFixed() {
  const items = [
    { n: '01', h: 'Case studies are passive', p: 'Students read, discuss, present. Nobody practises the actual skill - communicating with real stakeholders, under time pressure, with imperfect information.' },
    { n: '02', h: 'Role-plays don\'t scale',  p: 'A facilitator can play one character. Project Northstar runs twelve AI-powered stakeholders simultaneously across four or more teams in a single room.' },
    { n: '03', h: 'Assessment lacks rigour',  p: 'Faculty assess on feel, not evidence. There is no consistent standard, no audit trail, and nothing for students to learn from after the room empties.' },
  ];
  const [headRef, headSeen] = useInView({ threshold: 0.3 });
  return (
    <section className="section challenge" id="problem">
      <div className="container">
        <div className="challenge-head">
          <div className="section-eyebrow">The Challenge · 001</div>
          <h2 ref={headRef} className={`section-h2 mask-reveal ${headSeen ? 'in' : ''}`}>
            Why traditional teaching <em>falls short.</em>
          </h2>
          <p className="section-lead">
            Three structural gaps separate classroom learning from how consulting is actually practised. The simulation closes all three - in a single workshop.
          </p>
        </div>
        <div className="challenge-grid">
          {items.map((it, i) => <ChallengeCardV2 key={i} {...it} idx={i} />)}
        </div>
      </div>
    </section>
  );
}

function PageFixed() {
  useEffect(() => {
    const nav = document.getElementById('nav');
    const rail = document.getElementById('rail');
    const railPhase = document.getElementById('rail-phase');
    const railPct = document.getElementById('rail-pct');

    const phases = [
      { name: 'The Challenge',     from: 0.00 },
      { name: 'How It Works',      from: 0.18 },
      { name: 'The Facilitator',   from: 0.40 },
      { name: 'The Students',      from: 0.58 },
      { name: 'Engagement Model',  from: 0.74 },
      { name: 'Book a Demo',       from: 0.88 },
    ];

    const onScroll = () => {
      const y = window.scrollY;
      if (nav) nav.classList.toggle('scrolled', y > 30);
      if (rail) rail.classList.toggle('show', y > 220);

      const docH = document.documentElement.scrollHeight - window.innerHeight;
      const pct = docH > 0 ? Math.min(1, Math.max(0, y / docH)) : 0;
      if (rail) rail.style.setProperty('--scroll-pct', `${pct * 100}%`);
      if (railPct) railPct.textContent = String(Math.round(pct * 100)).padStart(2,'0') + '%';

      const cur = phases.slice().reverse().find((p) => pct >= p.from) || phases[0];
      if (railPhase) {
        railPhase.innerHTML = `<em>${cur.name}</em>`;
      }
    };

    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  useEffect(() => {
    const handler = (e) => {
      const a = e.target.closest && e.target.closest('a[href^="#"]');
      if (!a) return;
      const href = a.getAttribute('href');
      if (!href || href === '#') return;
      const t = document.querySelector(href);
      if (!t) return;
      e.preventDefault();
      t.scrollIntoView({ behavior: 'smooth', block: 'start' });
    };
    document.addEventListener('click', handler);
    return () => document.removeEventListener('click', handler);
  }, []);

  return (
    <>
      <Hero />
      <ChallengeFixed />
      <HowItWorks />
      <Faculty />
      <Students />
      <Pricing />
      <Book />
      <Footer />
    </>
  );
}

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