/* ==========================================================================
   Method.jsx  —  @role
   Method page (longest, ~15 screens). Sections: hero, three domains, evidence base, elite-sport cards (hover term tooltips), partners, how-applied, advisory. Mounts method-journey-v7.js module.
   ========================================================================== */
/* PSL Method Page — v5 enhanced (interactive)
   Same structure & copy as v4 tight, more interactivity & animation:
     - Scroll-triggered staggered fade-up for sections (IntersectionObserver)
     - Hero: animated highlight underline + drifting aurora blobs behind type
     - System rings: pulsing rings overlay (like the home page) + glow marker
       with springy easing, pop-in counters on the legend numbers
     - Practice cards: hover shimmer + sliding accent rule + count-up nums
     - Sources: ticker-style underline grow on view, count-up source numbers
     - Signature Insight: dark editorial spread with animated radial blooms
       + word-by-word reveal on the headline
     - What Changes: animated horizon timeline bars that fill on view
     - Steps: connecting rule that draws across all four numbers on view
     - CTA: hover shimmer on primary, gradient sweep on the dark band
*/

const { useState, useEffect, useRef, useMemo } = React;

/* ---------- shared anim helpers ---------- */
const useInView = (rootMargin = "-10% 0px -10% 0px") => {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (!ref.current || seen) return;
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {if (e.isIntersecting) {setSeen(true);io.disconnect();}});
      },
      { rootMargin, threshold: 0.05 }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, [rootMargin, seen]);
  return [ref, seen];
};

/* counter that animates 0 → target when in view (leading-zero, fixed width) */
const Counter = ({ to, pad = 2, duration = 900, className }) => {
  const [ref, seen] = useInView();
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!seen) 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(eased * to));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [seen, to, duration]);
  return <span ref={ref} className={className}>{String(val).padStart(pad, "0")}</span>;
};

/* =====================================================================
   SECTION NAVIGATION — one consistent set of section names, used by both
   the hero overview index and the sticky strip, with smooth jump-to.
   ===================================================================== */
const M_SECTIONS = [
  { label: "Origins",        id: "sec-origins",    desc: "Where it comes from" },
  { label: "The System",     id: "sec-system",     desc: "The three domains" },
  { label: "Practice Areas", id: "sec-practice",   desc: "How it's applied" },
  { label: "Evidence",       id: "sec-evidence",   desc: "The research base" },
  { label: "Insight",        id: "sec-insight",    desc: "A worked example" },
  { label: "Partners",       id: "sec-partners",   desc: "Who we bring in" },
  { label: "Engagement",     id: "sec-engagement", desc: "Diagnosis → advisory" }
];
const M_jumpTo = (id) => {
  const el = document.getElementById(id);
  if (!el) return;
  const target = Math.max(0, el.getBoundingClientRect().top + window.scrollY - 70);
  // Smooth-scroll via a manual rAF tween — robust where {behavior:"smooth"} is a no-op.
  const start = window.scrollY;
  const dist = target - start;
  if (Math.abs(dist) < 2) return;
  const dur = 520;
  let t0 = null;
  const step = (t) => {
    if (t0 === null) t0 = t;
    const p = Math.min((t - t0) / dur, 1);
    const eased = p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2;
    window.scrollTo(0, start + dist * eased);
    if (p < 1) requestAnimationFrame(step);
  };
  requestAnimationFrame(step);
};

/* Glossary term — coloured, dashed-underlined, hover/focus tooltip with a
   textbook-style definition. Signals "hover me" via the dashed underline. */
const M_Term = ({ children, def }) =>
  <span className="m-term" tabIndex={0} title={def}>
    {children}<span className="m-term-icon" aria-hidden>i</span>
    <span className="m-term-pop" role="tooltip">
      <span className="m-term-pop-label">Sports term</span>
      <span className="m-term-pop-def">{def}</span>
    </span>
  </span>;

/* =====================================================================
   01 — HERO
   ===================================================================== */
const M_Hero = () => {
  const [ref, seen] = useInView("0px");
  return (
    <section className={"m-hero m-hero-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-hero-aurora" aria-hidden>
        <span className="m-aurora m-aurora-1" />
        <span className="m-aurora m-aurora-2" />
        <span className="m-aurora m-aurora-3" />
      </div>
      <div className="m-hero-strip" aria-hidden>
        <div className="m-hero-strip-tile m-hero-strip-tile-1" style={{ backgroundImage: "url('assets/method/rugby-lg.jpg')" }} />
        <div className="m-hero-strip-tile m-hero-strip-tile-2" style={{ backgroundImage: "url('assets/method/boxing-lg.jpg')" }} />
        <div className="m-hero-strip-tile m-hero-strip-tile-3" style={{ backgroundImage: "url('assets/method/corporate-lg.jpg')" }} />
        <div className="m-hero-strip-veil" />
      </div>
      <div className="m-container">
        <span className="m-overline m-anim-fade m-anim-d0">THE PSL METHOD · PERFORMANCE UNDER PRESSURE</span>
        <h1 className="m-hero-h">
          <span className="m-anim-fadeup m-anim-d1">Under pressure, it’s rarely effort that fails.</span>{" "}
          <span className="m-anim-fadeup m-anim-d2">It’s the</span>{" "}<span className="m-anim-fadeup m-anim-d3 m-hero-mark">system underneath</span><span className="m-anim-fadeup m-anim-d3">.</span>
        </h1>
        <p className="m-hero-sub m-anim-fadeup m-anim-d4">
          A structured operating model for performance under sustained pressure — grounded in elite sport, organisational research, and a decade of complex delivery. Not generic wellbeing. Not motivational coaching.
        </p>
        <nav className="m-hero-nav m-anim-fadeup m-anim-d5" aria-label="Sections on this page">
          <span className="m-hero-nav-label">On this page</span>
          <ol className="m-hero-nav-list">
            {M_SECTIONS.map((s, i) =>
            <li key={s.id}>
                <button className="m-hero-nav-link" onClick={() => M_jumpTo(s.id)}>
                  <span className="m-hero-nav-num">{String(i + 1).padStart(2, "0")}</span>
                  <span className="m-hero-nav-text">
                    <span className="m-hero-nav-name">{s.label}</span>
                    <span className="m-hero-nav-desc">{s.desc}</span>
                  </span>
                </button>
              </li>
            )}
          </ol>
        </nav>
      </div>
    </section>);

};

/* =====================================================================
   02 — THE PERFORMANCE SYSTEM
   ===================================================================== */
const M_System = () => {
  const domains = [
  {
    id: "identity",
    label: "Performance Identity",
    desc: "WHO YOU ARE UNDER PRESSURE",
    body: "The values, standards, and behavioural anchors that determine how teams decide and behave when conditions are difficult.",
    failure: "Standards default downward, decisions become reactive, leadership alignment fragments under pressure that exposes what was assumed but never built.",
    pulseRing: 0
  },
  {
    id: "execution",
    label: "Execution Architecture",
    desc: "HOW YOU TURN INTENT INTO CONSISTENT ACTION",
    body: "The operating rhythms, decision rituals, and delivery structures that translate priorities into predictable output.",
    failure: "Effort is high but output is inconsistent. Delivery stalls despite engagement. Heroics become the way work gets done because the structural design is not there to do it instead.",
    pulseRing: 1
  },
  {
    id: "capacity",
    label: "Sustainable Capacity",
    desc: "HOW YOU MAINTAIN INTENSITY WITHOUT BREAKING",
    body: "The recovery design, workload management, and adaptive capacity that determines whether performance can be sustained.",
    failure: "The system does not collapse. It erodes. Output drops incrementally. Decision quality declines. Absence rises in the weeks after major delivery moments. Nobody can point to the moment things broke because nothing broke.",
    pulseRing: 2
  }];

  const [active, setActive] = useState(0);
  const [ref, seen] = useInView();
  const a = domains[active];

  return (
    <section id="sec-system" className={"m-section m-system m-system-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-container">
        <span className="m-overline">THE PERFORMANCE SYSTEM</span>
        <h2 className="m-h2">
          Three domains — the three rings of the Performance System.
        </h2>
        <p className="m-section-intro">
          The three rings of the PSL Performance System are three interconnected domains: <strong>Identity</strong>, <strong>Execution Architecture</strong>, and <strong>Sustainable Capacity</strong>. When all three are designed and aligned, execution becomes consistent. When any one is missing or weak, pressure finds it.
        </p>

        <div className="m-system-grid">
          {/* Rings — LEFT (matches home page animated rings) */}
          <div className="m-rings">
            {/* New embedded PSL Performance System animation (same as home page). */}
            <PSLPerfAnim activeIndex={active} />

            <ul className="m-rings-legend" role="tablist">
              {domains.map((d, i) =>
              <li key={d.id} role="presentation">
                  <button
                  role="tab"
                  aria-selected={i === active}
                  className={"m-rings-legend-item" + (i === active ? " active" : "")}
                  onClick={() => setActive(i)}
                  onMouseEnter={() => setActive(i)}>

                    <span className="m-rings-legend-num">{String(i + 1).padStart(2, "0")}</span>
                    <span className="m-rings-legend-text">
                      <span className="m-rings-legend-label">{d.label}</span>
                      <span className="m-rings-legend-desc">{d.desc}</span>
                    </span>
                    <span className="m-rings-legend-arrow" aria-hidden>→</span>
                  </button>
                </li>
              )}
            </ul>
          </div>

          {/* Panel — RIGHT */}
          <div className="m-system-panel" key={a.id}>
            <div className="m-system-panel-meta">
              <span className="m-system-panel-num">{String(active + 1).padStart(2, "0")}</span>
              <span className="m-system-panel-rule" />
              <span className="m-system-panel-desc">{a.desc}</span>
            </div>
            <h3 className="m-system-panel-h">{a.label}</h3>
            <p className="m-system-panel-body">{a.body}</p>

            <div className="m-failure">
              <span className="m-failure-label">
                <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
                  <path d="M2 4l5 5 3-3 4 4" />
                  <path d="M14 10v4h-4" />
                </svg>
                When it’s missing
              </span>
              <p className="m-failure-body">{a.failure}</p>
            </div>

            <div className="m-system-panel-tabs">
              {domains.map((d, i) =>
              <button
                key={d.id}
                className={"m-system-panel-tab" + (i === active ? " active" : "")}
                onClick={() => setActive(i)}
                aria-pressed={i === active}>

                  <span className="m-system-panel-tab-dot" />
                  {d.label}
                </button>
              )}
            </div>
          </div>
        </div>

        <div className="m-system-foot">
          <div className="m-system-foot-head">
            <div className="m-system-foot-chain" aria-hidden>
              <span className="m-system-foot-node" style={{ "--c": "#8936FF" }} />
              <span className="m-system-foot-link" />
              <span className="m-system-foot-node" style={{ "--c": "#0FB388" }} />
              <span className="m-system-foot-link" />
              <span className="m-system-foot-node" style={{ "--c": "#2563EB" }} />
            </div>
            <span className="m-system-foot-eyebrow">The system only holds as one</span>
          </div>
          <p className="m-system-foot-text">
            The three domains are not independent. A strong <strong style={{ color: "#8936FF" }}>Performance Identity</strong> without <strong style={{ color: "#0FB388" }}>Execution Architecture</strong> produces aspiration without delivery. Strong execution without <strong style={{ color: "#2563EB" }}>Sustainable Capacity</strong> produces short-term output at long-term cost. Designed together, or not at all.
          </p>
        </div>
      </div>
    </section>);

};

/* =====================================================================
   03 — FIVE PRACTICE AREAS (v6: lead + 4-supporting + ring indicators)
   Preserved old version available below.
   ===================================================================== */
const M_PracticeAreas_v1 = () => {
  const items = [
  { label: "Performance Identity Design", body: "Building the standards, anchors, and operating principles that determine how a team decides under pressure.", domain: "Identity" },
  { label: "Execution Rhythm and Architecture", body: "Designing the operating cadence, decision rituals, and delivery structures that produce predictable execution.", domain: "Execution" },
  { label: "Pressure Conditioning", body: "Building the readiness, composure, and pace tolerance required to perform under sustained consequence.", domain: "Identity · Execution" },
  { label: "Capacity and Recovery Design", body: "Engineering workload patterns, recovery cycles, and adaptive capacity so intensity sustains without deterioration.", domain: "Capacity" },
  { label: "Performance Transformation", body: "Restructuring how a team or organisation operates and identifies when sustained pressure has become the new permanent condition.", domain: "All three" }];

  const [ref, seen] = useInView();
  return (
    <section className={"m-section m-practice m-practice-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-container">
        <span className="m-overline">HOW THE SYSTEM IS APPLIED</span>
        <h2 className="m-h2">
          Five practice areas. The operational layer through which the three domains become applied work.
        </h2>

        <ol className="m-practice-grid">
          {items.map((it, i) =>
          <li key={i} className="m-practice-card" style={{ "--m-i": i }}>
              <div className="m-practice-num">
                <Counter to={i + 1} pad={2} />
              </div>
              <div className="m-practice-rule" />
              <h3 className="m-practice-label">{it.label}</h3>
              <p className="m-practice-body">{it.body}</p>
              <div className="m-practice-foot">
                <span className="m-practice-domain-label">DOMAIN</span>
                <span className="m-practice-domain-value">{it.domain}</span>
              </div>
              <span className="m-practice-shine" aria-hidden />
            </li>
          )}
        </ol>
      </div>
    </section>);

};

/* Ring-indicator pill — lights up the rings activated by each practice.
   Inner = Identity (violet), Middle = Execution (teal), Outer = Capacity (blue).
   Matches the home-page Breaks-Down card colour system. */
const M_RingIndicator = ({ active = [], size = 40 }) => {
  const has = (d) => active.includes(d);
  const dim = "rgba(13,0,66,0.14)";
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none" aria-hidden style={{ flexShrink: 0 }}>
      <circle cx="20" cy="20" r="17" stroke={has("capacity")  ? "#7C8AFF" : dim} strokeWidth="2" />
      <circle cx="20" cy="20" r="11" stroke={has("execution") ? "#2EE0B0" : dim} strokeWidth="2" />
      <circle cx="20" cy="20" r="5"  stroke={has("identity")  ? "#A78BFA" : dim} strokeWidth="2" />
    </svg>
  );
};

/* Domain affiliation tag — matches the home-page equation system
   (coloured dot + name per domain) instead of the corner ring glyph.
   identity = violet, execution = teal, capacity = blue. */
const M_DOMAIN_COLORS = { identity: "#8936FF", execution: "#0FB388", capacity: "#2563EB" };
const M_DOMAIN_NAMES  = { identity: "Identity", execution: "Execution", capacity: "Capacity" };
const M_DomainTag = ({ domains = [], labels = true, onDark = false }) =>
  <span className="m-domain-tag" style={{ display: "inline-flex", alignItems: "center", gap: labels ? 12 : 6, flexWrap: "wrap" }}>
    {domains.map((d) =>
    <span key={d} style={{
      display: "inline-flex", alignItems: "center", gap: 6,
      fontSize: 11.5, fontWeight: 600, letterSpacing: "0.01em",
      color: onDark ? "rgba(255,255,255,0.9)" : "#0D0042"
    }}>
        <span style={{ width: 7, height: 7, borderRadius: "50%", background: M_DOMAIN_COLORS[d], flexShrink: 0 }} />
        {labels ? M_DOMAIN_NAMES[d] : null}
      </span>
    )}
  </span>;

const M_PracticeAreas = () => {
  const lead = {
    n: "05",
    label: "Performance Transformation",
    body: "Restructuring how a team or organisation operates when sustained pressure has become the new permanent condition. The integrative practice — engaged when the underlying operating model needs to be redesigned end-to-end, not just adjusted. Combines the four operational disciplines into a coordinated programme that rebuilds the structural conditions under which performance happens, so the change holds beyond the engagement itself.",
    eyebrow: "THE INTEGRATIVE PRACTICE",
    footLabel: "All three domains, applied as one",
    domains: ["identity", "execution", "capacity"],
    img: "assets/photos/boardroom.jpg",
    imgAlt: "An executive boardroom — the room where operating models get restructured",
  };
  const supporting = [
    { n: "01", label: "Performance Identity Design",       body: "Building the standards, anchors, and operating principles that determine how a team decides under pressure.",                              engagement: "A redefined team charter and decision principles the team actually uses when the pressure is on.", domains: ["identity"],              domainLabel: "Identity" },
    { n: "02", label: "Execution Rhythm & Architecture",   body: "Designing the operating cadence, decision rituals, and delivery structures that produce predictable execution.",                            engagement: "A re-sequenced delivery cadence and decision rituals that tighten the forecast band.", domains: ["execution"],             domainLabel: "Execution" },
    { n: "03", label: "Pressure Conditioning",             body: "Building the readiness, composure, and pace tolerance required to perform under sustained consequence.",                                    engagement: "Rehearsed high-stakes scenarios so composure and pace hold as consequence rises.", domains: ["identity", "execution"], domainLabel: "Identity · Execution" },
    { n: "04", label: "Capacity & Recovery Design",        body: "Engineering workload patterns, recovery cycles, and adaptive capacity so intensity sustains without deterioration.",                        engagement: "Workload pacing and engineered recovery cycles built into the operating calendar.", domains: ["capacity"],              domainLabel: "Capacity" },
  ];

  const [ref, seen] = useInView();
  return (
    <section id="sec-practice" className={"m-section m-practice m-practice-v5" + (seen ? " is-in" : "")} ref={ref}>
      <style>{`
        .m-practice-layout {
          display: flex;
          flex-direction: column;
          gap: 28px;
          margin-top: 56px;
        }
        .m-practice-supporting {
          display: grid;
          grid-template-columns: repeat(4, 1fr);
          gap: 20px;
        }
        .m-practice-lead {
          position: relative;
          background: #FFFFFF;
          border: 1px solid rgba(13,0,66,0.08);
          border-radius: 16px;
          overflow: hidden;
          display: grid;
          grid-template-columns: 0.85fr 1.2fr;
          min-height: 360px;
          transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
        }
        /* Flat variant — Practice 05 as a single full-width text card
           (no image panel), shorter and consistent with the four above. */
        .m-practice-lead--flat {
          display: block;
          min-height: 0;
        }
        .m-practice-lead:hover {
          transform: translateY(-3px);
          box-shadow: 0 18px 40px rgba(13,0,66,0.10);
          border-color: rgba(31,77,216,0.30);
        }
        .m-practice-mini {
          position: relative;
          background: #FFFFFF;
          border: 1px solid rgba(13,0,66,0.08);
          border-radius: 14px;
          padding: 24px 22px 22px;
          display: flex;
          flex-direction: column;
          transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
        }
        .m-practice-mini:hover {
          transform: translateY(-3px);
          box-shadow: 0 14px 32px rgba(13,0,66,0.08);
          border-color: rgba(31,77,216,0.28);
        }
        @media (max-width: 1024px) {
          .m-practice-supporting { grid-template-columns: 1fr 1fr; }
          .m-practice-lead { grid-template-columns: 1fr; min-height: 0; }
          .m-practice-lead .m-practice-lead-img { min-height: 220px !important; }
        }
        @media (max-width: 560px) {
          .m-practice-supporting { grid-template-columns: 1fr; }
          .m-practice-lead-content { padding: 28px 24px 24px !important; }
        }
      `}</style>
      <div className="m-container">
        <span className="m-overline">HOW THE SYSTEM IS APPLIED</span>
        <h2 className="m-h2">
          Five practice areas. <span className="m-accent-blue">Four operational.</span> <span className="m-accent-blue">One integrative.</span>
        </h2>
        <p className="m-section-intro">
          The three domains describe how performance is structured. The five practice areas describe how the system is applied — four focused operational disciplines, plus the integrative practice that brings them together as a coordinated transformation.
        </p>

        <div className="m-practice-layout">
          {/* TOP ROW — 4 supporting practices in equal columns */}
          <div className="m-practice-supporting">
            {supporting.map((p) => (
              <article key={p.n} className="m-practice-mini">
                <div
                  style={{
                    display: "flex",
                    justifyContent: "space-between",
                    alignItems: "flex-start",
                    marginBottom: 16
                  }}
                >
                  <div
                    style={{
                      fontSize: 11,
                      fontWeight: 700,
                      letterSpacing: "0.2em",
                      color: "#1F4DD8"
                    }}
                  >
                    PRACTICE {p.n}
                  </div>
                  <M_DomainTag domains={p.domains} />
                </div>
                <h3
                  style={{
                    margin: 0,
                    fontSize: 17,
                    fontWeight: 600,
                    lineHeight: 1.25,
                    letterSpacing: "-0.01em",
                    color: "#0D0042",
                    textWrap: "balance"
                  }}
                >
                  {p.label}
                </h3>
                <p
                  style={{
                    margin: "12px 0 0",
                    fontSize: 14,
                    lineHeight: 1.55,
                    color: "rgba(13,0,66,0.72)",
                    flex: 1
                  }}
                >
                  {p.body}
                </p>
                <p
                  style={{
                    margin: "12px 0 0",
                    fontSize: 12.5,
                    lineHeight: 1.5,
                    color: "rgba(13,0,66,0.6)"
                  }}
                >
                  <span style={{ fontWeight: 700, color: "#1F4DD8", letterSpacing: "0.04em" }}>In an engagement:&nbsp;</span>
                  {p.engagement}
                </p>
              </article>
            ))}
          </div>

          {/* BOTTOM — Practice 05, flat full-width text card (no image panel),
              consistent with the four supporting cards. */}
          <article className="m-practice-lead m-practice-lead--flat">
            <div className="m-practice-lead-content" style={{ padding: "30px 34px", display: "flex", flexDirection: "column", gap: 0 }}>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, marginBottom: 14, flexWrap: "wrap" }}>
                <div style={{ display: "inline-flex", alignItems: "center", gap: 14, flexWrap: "wrap" }}>
                  <span style={{ fontSize: 12, fontWeight: 700, letterSpacing: "0.22em", color: "#1F4DD8" }}>
                    PRACTICE {lead.n} · {lead.eyebrow}
                  </span>
                  <M_DomainTag domains={lead.domains} />
                </div>
                <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: "0.18em", color: "rgba(13,0,66,0.55)", textTransform: "uppercase" }}>
                  {lead.footLabel}
                </span>
              </div>
              <h3
                style={{
                  margin: 0,
                  fontSize: 26,
                  fontWeight: 600,
                  lineHeight: 1.15,
                  letterSpacing: "-0.02em",
                  color: "#0D0042",
                  textWrap: "balance"
                }}
              >
                {lead.label}
              </h3>
              <p
                style={{
                  margin: "14px 0 22px",
                  fontSize: 15.5,
                  lineHeight: 1.6,
                  color: "rgba(13,0,66,0.78)",
                  maxWidth: 820
                }}
              >
                {lead.body}
              </p>

              {/* Synthesis diagram — the four operational practices feeding into Practice 05 */}
              <div
                style={{
                  marginTop: 4,
                  padding: "18px 18px",
                  background: "linear-gradient(180deg, rgba(31,77,216,0.04) 0%, rgba(46,224,176,0.04) 100%)",
                  border: "1px solid rgba(13,0,66,0.08)",
                  borderRadius: 12,
                  display: "flex",
                  alignItems: "center",
                  gap: 14,
                  flexWrap: "wrap"
                }}
              >
                <div
                  style={{
                    fontSize: 10,
                    fontWeight: 700,
                    letterSpacing: "0.18em",
                    color: "rgba(13,0,66,0.55)",
                    textTransform: "uppercase",
                    flexBasis: "100%",
                    marginBottom: 4
                  }}
                >
                  Synthesises practices 01 → 04
                </div>
                {supporting.map((p, i) => (
                  <React.Fragment key={p.n}>
                    <div
                      style={{
                        display: "inline-flex",
                        alignItems: "center",
                        gap: 8,
                        padding: "8px 12px",
                        background: "#fff",
                        border: "1px solid rgba(13,0,66,0.10)",
                        borderRadius: 999,
                        fontSize: 12,
                        fontWeight: 600,
                        color: "#0D0042"
                      }}
                    >
                      <M_DomainTag domains={p.domains} labels={false} />
                      <span style={{ whiteSpace: "nowrap" }}>{p.n} {p.label.replace(/&/g, "&").split("&")[0].trim().split(" ").slice(0, 2).join(" ")}</span>
                    </div>
                    {i < supporting.length - 1 && (
                      <span aria-hidden style={{ color: "rgba(13,0,66,0.30)", fontSize: 14, fontWeight: 700 }}>+</span>
                    )}
                  </React.Fragment>
                ))}
                <span aria-hidden style={{ color: "rgba(13,0,66,0.45)", fontSize: 16, fontWeight: 700, margin: "0 4px" }}>→</span>
                <div
                  style={{
                    display: "inline-flex",
                    alignItems: "center",
                    gap: 8,
                    padding: "8px 12px",
                    background: "#0D0042",
                    color: "#fff",
                    borderRadius: 999,
                    fontSize: 12,
                    fontWeight: 700
                  }}
                >
                  <M_DomainTag domains={lead.domains} labels={false} onDark />
                  <span style={{ whiteSpace: "nowrap" }}>05 Transformation</span>
                </div>
              </div>
            </div>
          </article>
        </div>
      </div>
    </section>
  );
};

/* =====================================================================
   04 — SOURCES
   ===================================================================== */
const M_Sources = () => {
  const sources = [
  { tag: "Source 01", label: "Organisational research", color: "#2563EB", meta: "Google’s Project Aristotle · McKinsey · Gallup", stat: "180+ teams · 20,000+ people studied", finding: "The external evidence is consistent: sustained team performance is a property of the operating system, not of individual talent. Google’s Project Aristotle isolated psychological safety and clear decision rituals as the strongest predictors of effectiveness — ahead of raw ability. McKinsey’s organisational-health research links operating discipline to durable financial outperformance, and Gallup’s engagement studies tie how a team is structured to measurable productivity. Different methods, same conclusion: structure beats talent." },
  { tag: "Source 02", label: "Performance science", color: "#0FB388", meta: "Periodisation · Recovery science · Load management", stat: "A century of applied research", finding: "From the labs and training environments behind elite sport: performance under contested pressure is engineered, not innate. Designed load cycles, structured recovery, and rehearsed roles make intensity repeatable and trainable. The same physiology and psychology that govern an athlete in competition govern a team under sustained delivery pressure — measurable, and trainable." },
  { tag: "Source 03", label: "Our own active research", color: "#8936FF", meta: "PSL research arm · published to Insights", stat: "10+ years · ongoing live engagements", finding: "We don’t just consume the evidence — we extend it. Across ten-plus years and a continuous stream of live client engagements, PSL studies how performance behaves under real delivery pressure, captures what works on the ground, and publishes the findings to our Insights hub — feeding every lesson straight back into the guidance we give clients.", href: "insights.html" }];

  const [ref, seen] = useInView();
  return (
    <section id="sec-evidence" className={"m-section m-foundations m-foundations-v5" + (seen ? " is-in" : "")} ref={ref} style={{ scrollMarginTop: 80 }}>
      <div className="m-container">
        <span className="m-overline">THE EVIDENCE BASE</span>
        <h2 className="m-h2">The research beneath the method.</h2>
        <p className="m-section-intro">
          The environments above are where the thinking is drawn from. This is the evidence beneath it: established organisational research, the performance science behind elite sport, and PSL's own ongoing studies. Each is named alongside the specific finding it contributes.
        </p>

        <ul className="m-sources-grid">
          {sources.map((s, i) =>
          <li key={i} className={"m-source" + (s.href ? " m-source-linked" : "")} style={{ "--m-i": i, "--p-c": s.color, position: "relative" }}>
              {s.href &&
              <a href={s.href} aria-label={`Visit the Insights Hub`} style={{ position: "absolute", inset: 0, zIndex: 2, borderRadius: "inherit" }} />
              }
              <span className="m-source-tag">
                Source <Counter to={i + 1} pad={2} />
              </span>
              <h3 className="m-source-label">{s.label}</h3>
              <span className="m-source-meta">{s.meta}</span>
              {s.stat ? <span className="m-source-stat">{s.stat}</span> : null}
              {s.finding ? <p className="m-source-finding">{s.finding}</p> : null}
              {s.href &&
              <span style={{
                marginTop: 14,
                fontSize: 12,
                fontWeight: 700,
                letterSpacing: "0.14em",
                textTransform: "uppercase",
                color: "var(--m-blue, #1F4DD8)",
                display: "inline-flex",
                alignItems: "center",
                gap: 8
              }}>
                Visit the Insights Hub
                <svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
                  <path d="M3 8h10M9 4l4 4-4 4" />
                </svg>
              </span>
              }
              <span className="m-source-bar" aria-hidden />
            </li>
          )}
        </ul>

        {/* Connective lead-in — frames the dark article that follows as the
           worked example from Source 03, keeping it within the evidence story. */}
        <a className="m-evidence-next" href="#sec-insight" onClick={(e) => { e.preventDefault(); M_jumpTo('sec-insight'); }}>
          <span className="m-evidence-next-meta">
            <span className="m-evidence-next-label">From Source 03 · Our active research</span>
            <span className="m-evidence-next-title">See one finding from that research, in full</span>
          </span>
          <span className="m-evidence-next-cta" aria-hidden>↓</span>
        </a>
      </div>
    </section>);

};

/* =====================================================================
   04c — PARTNERS (icon-chip pills bouncing off each other + a central CTA)
   ===================================================================== */
const M_PARTNER_ICONS = {
  glove:  '<path d="M7 9a4 4 0 0 1 8 0v2h1.6a2 2 0 0 1 2 2v1.2a4 4 0 0 1-4 4H9.2A3.2 3.2 0 0 1 6 16.2V10a1 1 0 0 1 1-1Z"/><path d="M7 14h2.2"/>',
  swim:   '<circle cx="9" cy="7" r="1.7"/><path d="M10.4 7.6 14 10l-3.2 2.1"/><path d="M3 16.4c1.4 1 2.7 1 4 0s2.6-1 4 0 2.6 1 4 0 2.6-1 4 0"/>',
  rugby:  '<g transform="rotate(-32 12 12)"><ellipse cx="12" cy="12" rx="8.6" ry="5"/><path d="M9 12h6"/><path d="M10.6 10.8v2.4M13.4 10.8v2.4"/></g>',
  run:    '<circle cx="14.4" cy="5.4" r="1.7"/><path d="M13.4 8.2 10 11.4l2.2 1.9-1.1 4.5"/><path d="M12.2 13.3 16.4 14.6"/><path d="M9 11.2 5.8 12.4"/>',
  oar:    '<path d="M4.5 19.5 16 8"/><path d="M16.2 5.6c2-1 3.9 1 2.9 3-.7 1.3-2.2 1.5-3.3 1l-.9-.9c-.5-1 .1-2.5 1.3-3.1Z"/>',
  case:   '<rect x="4" y="8.2" width="16" height="11" rx="2"/><path d="M9 8.2V6.4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v1.8"/><path d="M4 13.2h16"/>',
  pulse:  '<path d="M3 12.2h3.8l2-5.4 3.2 10.4 2.2-5h6"/>',
  shield: '<path d="M12 3.2 5.2 6v5.2c0 4 3 6.9 6.8 8.6 3.8-1.7 6.8-4.6 6.8-8.6V6L12 3.2Z"/><path d="M9.4 12l1.9 1.9 3.3-3.7"/>',
  rocket: '<path d="M12 3.2c3 1.6 5 5.1 5 9.2l-2 2H9l-2-2c0-4.1 2-7.6 5-9.2Z"/><circle cx="12" cy="9.2" r="1.6"/><path d="M9 16.2 7 20.4M15 16.2 17 20.4"/>'
};
const M_PARTNERS = [
  { label: "Professional Boxers", icon: "glove",  c: "#5B82FF", c2: "#2E4FE0" },
  { label: "Olympic Swimmers",    icon: "swim",   c: "#21CBE6", c2: "#0E8FD6" },
  { label: "Professional Rugby",  icon: "rugby",  c: "#34D17F", c2: "#119E6A" },
  { label: "Marathon Runners",    icon: "run",    c: "#A87BFA", c2: "#7C4DF0" },
  { label: "Doctors",             icon: "pulse",  c: "#2FD3B4", c2: "#12A98C" },
  { label: "Special Forces",      icon: "shield", c: "#6D6BFF", c2: "#4646B9" },
  { label: "C-Suite Leaders",     icon: "case",   c: "#8B88FF", c2: "#5D5BE6" },
  { label: "Founders",            icon: "rocket", c: "#C08BFF", c2: "#8B4DF0" }
];

const M_PartnersNetwork = () => {
  const stageRef = React.useRef(null);
  const ctaRef = React.useRef(null);
  const nodeRefs = React.useRef([]);

  React.useEffect(() => {
    const stage = stageRef.current, cta = ctaRef.current;
    if (!stage || !cta) return;
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const els = nodeRefs.current.filter(Boolean);
    let items = [], raf, last = null, rT;
    const obstacle = { cx: 0, cy: 0, r: 0 };
    const clamp = (v, lo, hi) => (v < lo ? lo : v > hi ? hi : v);

    const measureObstacle = () => {
      obstacle.cx = stage.clientWidth / 2;
      obstacle.cy = stage.clientHeight / 2;
      obstacle.r = Math.max(cta.offsetWidth, cta.offsetHeight) / 2 + 14;
    };
    const overlap = (a, b) => a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
    const hitsObstacle = (it) => {
      const rx = clamp(obstacle.cx, it.x, it.x + it.w), ry = clamp(obstacle.cy, it.y, it.y + it.h);
      const dx = obstacle.cx - rx, dy = obstacle.cy - ry;
      return dx * dx + dy * dy < obstacle.r * obstacle.r;
    };
    const draw = () => { for (let i = 0; i < items.length; i++) items[i].el.style.transform = "translate(" + items[i].x + "px," + items[i].y + "px)"; };
    const resolveWalls = (it, bw, bh) => {
      if (it.x <= 0) { it.x = 0; it.vx = Math.abs(it.vx); }
      else if (it.x + it.w >= bw) { it.x = bw - it.w; it.vx = -Math.abs(it.vx); }
      if (it.y <= 0) { it.y = 0; it.vy = Math.abs(it.vy); }
      else if (it.y + it.h >= bh) { it.y = bh - it.h; it.vy = -Math.abs(it.vy); }
    };
    const resolveObstacle = (it) => {
      const rx = clamp(obstacle.cx, it.x, it.x + it.w), ry = clamp(obstacle.cy, it.y, it.y + it.h);
      let nx = rx - obstacle.cx, ny = ry - obstacle.cy, dist = Math.sqrt(nx * nx + ny * ny);
      if (dist >= obstacle.r) return;
      if (dist < 0.0001) { nx = (it.x + it.w / 2) - obstacle.cx; ny = (it.y + it.h / 2) - obstacle.cy; dist = Math.sqrt(nx * nx + ny * ny) || 1; }
      const ux = nx / dist, uy = ny / dist, pen = obstacle.r - dist;
      it.x += ux * pen; it.y += uy * pen;
      const vdot = it.vx * ux + it.vy * uy;
      if (vdot < 0) { it.vx -= 2 * vdot * ux; it.vy -= 2 * vdot * uy; }
    };
    const resolvePair = (a, b) => {
      const dx = (a.x + a.w / 2) - (b.x + b.w / 2), dy = (a.y + a.h / 2) - (b.y + b.h / 2);
      const ox = (a.w + b.w) / 2 - Math.abs(dx), oy = (a.h + b.h) / 2 - Math.abs(dy);
      if (ox <= 0 || oy <= 0) return;
      if (ox < oy) { const sx = dx < 0 ? -1 : 1; a.x += sx * ox / 2; b.x -= sx * ox / 2; const t = a.vx; a.vx = b.vx; b.vx = t; }
      else { const sy = dy < 0 ? -1 : 1; a.y += sy * oy / 2; b.y -= sy * oy / 2; const t = a.vy; a.vy = b.vy; b.vy = t; }
    };
    const build = () => {
      const bw = stage.clientWidth, bh = stage.clientHeight;
      measureObstacle();
      items = els.map((el) => ({ el, w: el.offsetWidth, h: el.offsetHeight, x: 0, y: 0, vx: 0, vy: 0 }));
      items.forEach((it) => {
        let placed = false, tries = 0;
        while (!placed && tries < 400) {
          tries++;
          it.x = Math.random() * Math.max(1, bw - it.w);
          it.y = Math.random() * Math.max(1, bh - it.h);
          if (hitsObstacle(it)) continue;
          placed = true;
          for (let k = 0; k < items.length; k++) { const o = items[k]; if (o === it || o.w === 0) continue; if (overlap(it, o)) { placed = false; break; } }
        }
        const speed = 40 + Math.random() * 26, ang = Math.random() * Math.PI * 2;
        it.vx = Math.cos(ang) * speed; it.vy = Math.sin(ang) * speed;
      });
      draw();
    };
    const tick = (t) => {
      if (last == null) last = t;
      const dt = Math.min((t - last) / 1000, 0.032); last = t;
      const bw = stage.clientWidth, bh = stage.clientHeight;
      for (let i = 0; i < items.length; i++) { const it = items[i]; it.x += it.vx * dt; it.y += it.vy * dt; resolveWalls(it, bw, bh); resolveObstacle(it); }
      for (let pass = 0; pass < 2; pass++) {
        for (let a = 0; a < items.length; a++) for (let b = a + 1; b < items.length; b++) resolvePair(items[a], items[b]);
        for (let c = 0; c < items.length; c++) { resolveWalls(items[c], bw, bh); resolveObstacle(items[c]); }
      }
      draw();
      raf = requestAnimationFrame(tick);
    };
    build();
    if (!reduced) raf = requestAnimationFrame(tick);
    const onResize = () => { clearTimeout(rT); rT = setTimeout(build, 180); };
    window.addEventListener("resize", onResize);
    return () => { cancelAnimationFrame(raf); clearTimeout(rT); window.removeEventListener("resize", onResize); };
  }, []);

  return (
    <section id="sec-partners" className="m-section m-partners-section">
      <div className="m-container">
    <div className="m-partners">
      <div className="m-partners-copy">
        <span className="m-partners-eyebrow">Our partners</span>
        <h3 className="m-partners-h">We bring high performance into the room.</h3>
        <p className="m-partners-p">
          We partner with people who perform under real pressure — elite athletes alongside leaders from the highest-stakes fields — and bring them into client workshops, live. They share what actually holds when it counts, and it feeds our thinking on every engagement.
        </p>
      </div>
      <div className="m-partners-stage" ref={stageRef} aria-label="Examples of the partners we work with">
        <a className="pp-cta" ref={ctaRef} href="diagnostic.html" aria-label="Work with us">
          <span className="pp-cta-label">Work<br />with us</span>
          <span className="pp-cta-badge" aria-hidden="true">
            <svg viewBox="0 0 24 24"><path d="M7 17 17 7" /><path d="M8 7h9v9" /></svg>
          </span>
        </a>
        {M_PARTNERS.map((p, i) =>
        <span
            key={i}
            className="pp"
            ref={(el) => (nodeRefs.current[i] = el)}
            style={{ "--c": p.c, "--c2": p.c2 }}>
            <span className="pp-chip" dangerouslySetInnerHTML={{ __html: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' + M_PARTNER_ICONS[p.icon] + '</svg>' }} />
            <span className="pp-label">{p.label}</span>
          </span>
        )}
      </div>
    </div>
      </div>
    </section>
  );
};

/* =====================================================================
   04b — ORIGINS (sport + corporate references)
   ===================================================================== */
const M_Origins = () => {
  const tiles = [
  {
    img: "assets/method/rugby-lg.jpg",
    video: "assets/method/rugby-origin.mp4",
    tag: "Elite-sport principles",
    source: "Professional rugby squad · training",
    h: "Rugby — the scrum.",
    body: "Eight players bind as one to absorb contested force and win the ball. Roles set before engagement, the structure rehearsed until it holds when conditions go non-linear.",
    lesson: "Performance Identity · Execution Architecture"
  },
  {
    img: "assets/method/boxing-lg.jpg",
    video: "assets/method/boxing-origin.mp4",
    tag: "Periodisation & load",
    source: "Team GB · Olympic boxing final",
    h: "Boxing — the round.",
    body: "Twelve cycles of contested intensity. What looks like raw aggression is a precisely engineered structure of load, pace, and recovery — the clearest example of performance built by design.",
    lesson: "Sustainable Capacity"
  },
  {
    img: "assets/method/corporate-lg.jpg",
    video: "assets/method/corporate-origin.mp4",
    tag: "A decade of complex delivery",
    source: "Tech delivery team · echoing Google’s Project Aristotle",
    h: "The team that has to deliver.",
    body: "The same principles, mapped to financial services, global retail, and enterprise technology. Sustained pressure. Contested priorities. Decisions made on incomplete information against unforgiving timelines.",
    lesson: "All three domains, applied"
  }];

  const boxing = {
    sport: "Championship Boxing",
    color: "#2563EB",
    rings: ["capacity", "identity"],
    why: "Ranked the #1 hardest sport in the world by ESPN’s Sports Science panel — nowhere is performance under pressure more exposed.",
    points: [
    { term: "Fight camp", def: "Boxing: the 6–12 week training period a fighter does to get ready for a specific fight, planned so they peak on the night.", rest: "— effort built in blocks",
      what: "The fighters we’ve spoken to are clear: build up, sharpen, then ease off right before the fight, so the best of you arrives on the night.",
      translate: "Design effort in deliberate blocks toward the moment that matters — don’t run flat-out all year. The same goes for a team." },
    { termIn: "Discipline holds under ", term: "fatigue", def: "Sport & fitness: the build-up of physical and mental tiredness from training or working too hard — when it’s hardest to keep your standards up.", rest: "",
      what: "The hardest thing to hold, the fighters tell us, is discipline once tiredness sets in — in training, and deep in the late rounds. That’s the part they find toughest of all.",
      translate: "It’s exactly where teams slip too — standards quietly drop late on, once the pressure’s been on a while." },
    { term: "Sparring", def: "Boxing: practice rounds against a partner, used to rehearse technique, timing and composure under realistic conditions.", rest: "— rehearsal under live conditions",
      what: "The point the fighters make: you never want to feel that pressure for the first time on fight night — so they rehearse it, over and over, until it’s familiar.",
      translate: "Teams shouldn’t either — rehearse under realistic pressure first, so it’s familiar when it counts." }]
  };
  const otherSports = [
  { sport: "Professional Rugby", color: "#0FB388", rings: ["execution", "identity"], why: "Rugby runs on teamwork — every player bound to a shared code.", term: "The scrum", def: "Rugby: when the two packs of forwards lock together and push against each other to win the ball.", rest: "— the team bound as one",
    what: "Every player knows their exact job before it sets. The coaches we’ve spoken to call it pure coordinated execution under pressure — held by structure, not heroics.",
    translate: "Rehearse the structure until it just holds — it’s the same for a team when things get heavy." },
  { sport: "Marathon Running", color: "#8936FF", rings: ["capacity"], why: "Endurance is a mindset sport — won in the head as much as the legs.", term: "The negative split", def: "Distance running: running the second half of a race faster than the first — pacing yourself early so you finish strong.", rest: "— energy saved for the finish",
    what: "Runners we’ve spoken to swear by it: hold back early so there’s something left when it counts, rather than emptying the tank in the first mile.",
    translate: "Ration your output across the whole distance, not up front — that’s what keeps a team’s delivery sustainable to the line." },
  { sport: "Olympic Swimming", color: "#4644B9", rings: ["capacity"], why: "Swimming is all about practice and technique — tiny margins, endlessly refined.", term: "The taper", def: "Sport science: easing back on training just before a competition so the body is fresh and fast on the day.", rest: "— peak performance when it counts",
    what: "Swimmers we’ve spoken to time it to the day: cut right back beforehand so they turn up fresh and fast, with the peak landing exactly when it counts.",
    translate: "Aim the intensity at the moment that matters, rather than running flat-out the whole time." }];

  const [ref, seen] = useInView();
  const gridRef = React.useRef(null);
  React.useEffect(() => {
    if (!seen) return;
    const root = gridRef.current;
    if (!root) return;
    root.querySelectorAll(".m-origin-video").forEach((v) => {
      const p = v.play && v.play();
      if (p && p.then) p.then(() => { v.classList.add("is-playing"); }).catch(() => {});
      else v.classList.add("is-playing");
    });
  }, [seen]);
  return (
    <section id="sec-origins" className={"m-section m-origins m-origins-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-container" ref={gridRef}>
        <span className="m-overline">WHERE THE METHODOLOGY COMES FROM</span>
        <h2 className="m-h2">
          The discipline is borrowed from environments where pressure is the design constraint.
        </h2>
        <p className="m-section-intro">
          Elite sport and sport science have spent more than a century studying one question: how human performance behaves under sustained, contested pressure. The answers are structural and measurable — a researched field, not motivation. The same logic maps directly into the corporate environments where the same conditions apply, but the language for them is rarely built. PSL is the bridge between the two.
        </p>
        <ul className="m-origins-grid">
          {tiles.map((t, i) =>
          <li key={i} className="m-origin" style={{ "--m-i": i }}>
              <div className="m-origin-frame">
                <img src={t.img} alt={t.h} loading="lazy" />
                {t.video &&
                <video className="m-origin-video" src={t.video}
                  muted loop playsInline preload="metadata" aria-hidden="true" />
                }
                <span className="m-origin-tag">{t.tag}</span>
                {t.source &&
                <span className="m-origin-source">
                  <span className="m-origin-source-dot" aria-hidden />
                  {t.source}
                </span>
                }
              </div>
              <h3 className="m-origin-h">{t.h}</h3>
              <p className="m-origin-body">{t.body}</p>
              <div className="m-origin-foot">
                <span className="m-origin-foot-label">Maps to</span>
                <span className="m-origin-foot-value">{t.lesson}</span>
              </div>
            </li>
          )}
        </ul>

        {/* What elite sport teaches — boxing as the deep example (left),
            three more disciplines (right). Coloured tags, no left rule. */}
        <div className="m-elite">
          <div className="m-principles-head">
            <span className="m-principles-eyebrow">What Elite Sport Teaches Us</span>
          </div>
          <div className="m-elite-grid">
            <article className="m-elite-lead" style={{ "--p-c": boxing.color }}>
              <div className="m-elite-taghead">
                <span className="m-elite-sport">{boxing.sport}</span>
              </div>
              <p className="m-elite-why">{boxing.why}</p>
              <ul className="m-elite-points">
                {boxing.points.map((pt, i) =>
                <li key={i} className="m-elite-point">
                    <span className="m-elite-point-n">{String(i + 1).padStart(2, "0")}</span>
                    <span className="m-elite-point-text">
                      <p className="m-elite-point-body">
                        <strong className="m-elite-lead-in">{pt.termIn}<M_Term def={pt.def}>{pt.term}</M_Term>{pt.rest ? " " + pt.rest : ""}.</strong>{" "}
                        {pt.what}
                      </p>
                      <span className="m-elite-translate">
                        <span className="m-elite-translate-label">How this translates</span>
                        {pt.translate}
                      </span>
                    </span>
                  </li>
                )}
              </ul>
            </article>
            <div className="m-elite-right">
              {otherSports.map((s, i) =>
              <article key={i} className="m-elite-card" style={{ "--p-c": s.color, "--m-i": i }}>
                  <div className="m-elite-taghead">
                    <span className="m-elite-sport">{s.sport}</span>
                  </div>
                  <p className="m-elite-why">{s.why}</p>
                  <p className="m-elite-card-body">
                    <strong className="m-elite-lead-in"><M_Term def={s.def}>{s.term}</M_Term>{s.rest ? " " + s.rest : ""}.</strong>{" "}
                    {s.what}
                  </p>
                  <p className="m-elite-translate">
                    <span className="m-elite-translate-label">How this translates</span>
                    {s.translate}
                  </p>
                </article>
              )}
            </div>
          </div>
        </div>
      </div>
    </section>);

};

/* =====================================================================
   05 — SIGNATURE INSIGHT
   ===================================================================== */
const M_Insight = () => {
  const [ref, seen] = useInView("-15% 0px -15% 0px");
  return (
    <section id="sec-insight" className={"m-section m-insight m-insight-v5" + (seen ? " is-in" : "")} ref={ref} style={{ scrollMarginTop: 80 }}>
      <div className="m-insight-bg" aria-hidden>
        <span className="m-bloom m-bloom-1" />
        <span className="m-bloom m-bloom-2" />
        <span className="m-bloom m-bloom-3" />
      </div>
      <div className="m-container">
        <div className="m-insight-shell">
          <div className="m-insight-head">
            <span className="m-insight-kicker">
              <span aria-hidden style={{ color: "#8936FF" }}>↳</span>
              From Source 03 · Our active research
            </span>
            <span className="m-overline m-overline-on-dark">
              Sustainable Capacity
            </span>
            <h2 className="m-insight-article-title">Your Key Engineer Just Took Three Days Off. The Reason Should Worry You.</h2>
            <div className="m-insight-dateline">
              <span>PSL Research</span>
              <span className="m-insight-dateline-dot" aria-hidden />
              <span>9 May 2026</span>
              <span className="m-insight-dateline-dot" aria-hidden />
              <span>8 min read</span>
            </div>
            <div className="m-insight-pullquote">
              <span className="m-insight-quotemark" aria-hidden>“</span>
              <p className="m-insight-h m-insight-h--fade">
                Recovery is inevitable. The only question is whether it is planned and productive, or unplanned and disruptive.
              </p>
            </div>
            <div className="m-insight-stat">
              <span className="m-insight-stat-num"><Counter to={100} pad={1} duration={1400} /><span className="m-insight-stat-pct">%</span></span>
              <span className="m-insight-stat-label">of high-pressure delivery cycles trigger recovery — the only variable is whether it is engineered or extracted.</span>
            </div>
          </div>

          <div className="m-insight-body">
            <p>
              This is the structural reframe at the heart of the Sustainable Capacity domain. In high-pressure delivery environments, recovery is treated as a luxury or an afterthought. Teams push through major cycles without structured recovery time. The work goes out. The deliverable lands.
            </p>
            <p>
              And then something happens that nobody connects back to the cause. Sick days rise. Engagement drops. Decision quality declines. Output thins. The recovery time that was not built into the system arrives anyway, in unplanned form. The body and mind reclaim what was not formally designed in.
            </p>
            <p>
              <strong>Engineered recovery cycles, structured workload pacing, and adaptive capacity design are not soft interventions.</strong> They are the structural design that prevents the most expensive failure pattern in sustained-pressure delivery.
            </p>

            <a className="m-insight-source" href="articles/Your Key Engineer Just Took Three Days Off.html">
              <span className="m-insight-source-meta">
                <span className="m-insight-source-eyebrow">Continue reading on the Insights Hub</span>
                <span className="m-insight-source-title">The full article — what to build, and how it’s diagnosed</span>
              </span>
              <span className="m-insight-source-cta">
                Read the full article
                <svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
                  <path d="M3 8h10M9 4l4 4-4 4" />
                </svg>
              </span>
            </a>
          </div>
        </div>
      </div>
    </section>);

};

/* =====================================================================
   06 — WHAT CHANGES (animated horizons)
   ===================================================================== */
const M_WhatChanges = () => {
  const horizons = [
  {
    window: "Within 90 days",
    progressLabel: "Operating rhythm lands",
    barFill: 0.35,
    barRange: "0 — 90 days",
    label: "Operating rhythm and execution architecture interventions land.",
    body: "Delivery becomes more predictable. Heroics decrease. The team starts producing consistent output without working harder. Leadership begins to forecast inside a tight delivery band rather than a wide one.",
    tags: ["Predictable delivery", "Fewer heroics", "Tight forecast band"]
  },
  {
    window: "Across 6 to 12 months",
    progressLabel: "Capacity returns compound",
    barFill: 1,
    barRange: "0 — 12 months",
    label: "Sustainable Capacity work shows its returns.",
    body: "The team absorbs difficult delivery cycles without the post-cycle deterioration that previously followed. Unplanned absence patterns shift. Engagement holds through pressure rather than dropping in the wake of it. The team becomes increasingly difficult to break.",
    tags: ["Cycle resilience", "Engagement holds", "Difficult to break"]
  }];

  const [ref, seen] = useInView();
  return (
    <section className={"m-section m-changes m-changes-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-container">
        <span className="m-overline">WHAT THIS LOOKS LIKE WHEN IT IS IN PLACE</span>
        <h2 className="m-h2">The pattern of change is structural, not motivational.</h2>

        <div className="m-changes-grid">
          {horizons.map((h, i) =>
          <article key={i} className="m-horizon" style={{ "--m-i": i }}>
              <div className="m-horizon-window">
                <span className="m-horizon-window-num">
                  <Counter to={i + 1} pad={2} />
                </span>
                <span className="m-horizon-window-label">{h.window}</span>
              </div>

              <div className="m-horizon-track">
                <div className="m-horizon-track-bar" style={{ "--fill": h.barFill }} />
                <div className="m-horizon-track-meta">
                  <span>{h.progressLabel}</span>
                  <span>{h.barRange}</span>
                </div>
              </div>

              <h3 className="m-horizon-h">{h.label}</h3>
              <p className="m-horizon-body">{h.body}</p>
              <ul className="m-horizon-tags">
                {h.tags.map((t, j) => <li key={j}>{t}</li>)}
              </ul>
            </article>
          )}
        </div>
      </div>
    </section>);

};

/* =====================================================================
   07 — HOW ENGAGEMENTS RUN
   ===================================================================== */
const M_Steps = () => {
  const steps = [
  { label: "Diagnosis", body: "Every engagement begins with a diagnostic scored across the three domains. Evidence replaces assumption." },
  { label: "Insight and Interpretation", body: "Diagnostic data is translated into a structured Performance Profile Report, with a review session where useful." },
  { label: "Intervention and Design", body: "Targeted interventions across the relevant practice areas. Format is matched to the diagnosis." },
  { label: "Ongoing Advisory", body: "Quarterly Performance System Reviews provide structural oversight where performance is a sustained commercial priority." }];

  const [ref, seen] = useInView();
  return (
    <section className={"m-section m-steps m-steps-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-container">
        <span className="m-overline">FROM DIAGNOSIS TO ONGOING ADVISORY</span>
        <h2 className="m-h2">
          A structured progression from evidence to insight to intervention to advisory.
        </h2>

        <div className="m-steps-track" aria-hidden>
          <span className="m-steps-track-line" />
        </div>
        <ol className="m-steps-grid">
          {steps.map((s, i) =>
          <li key={i} className="m-step" style={{ "--m-i": i }}>
              <div className="m-step-dot" aria-hidden />
              <div className="m-step-num"><Counter to={i + 1} pad={2} /></div>
              <div className="m-step-rule" />
              <h3 className="m-step-label">{s.label}</h3>
              <p className="m-step-body">{s.body}</p>
            </li>
          )}
        </ol>
      </div>
    </section>);

};

/* =====================================================================
   06+07 — JOURNEY (merged: how engagements run + pattern of change)
   ===================================================================== */
const M_Journey = () => {
  const stops = [
  {
    window: "Pre-engagement",
    label: "Diagnosis",
    body: "Every engagement begins with a diagnostic scored across the three domains. Evidence replaces assumption.",
    deliverable: "Aggregated diagnostic readout across Identity, Architecture, Capacity",
    barFill: 0.05,
    tags: []
  },
  {
    window: "Weeks 1 – 4",
    label: "Insight & Interpretation",
    body: "Diagnostic data is translated into a structured Performance Profile Report, with a review session where useful.",
    deliverable: "Performance Profile Report + interpretation session",
    barFill: 0.25,
    tags: []
  },
  {
    window: "Within 90 days",
    label: "Intervention & Design",
    body: "Targeted interventions across the relevant practice areas. Operating rhythm and execution architecture land — delivery becomes more predictable, heroics decrease, and forecasts tighten.",
    deliverable: "Board-ready operating model recommendation + phased intervention plan",
    barFill: 0.6,
    tags: ["Predictable delivery", "Fewer heroics", "Tight forecast band"]
  },
  {
    window: "6 – 12 months",
    label: "Ongoing Advisory",
    body: "Quarterly Performance System Reviews provide structural oversight. Sustainable Capacity work shows its returns — cycles become resilient, engagement holds through pressure, and the team becomes increasingly difficult to break.",
    deliverable: "Quarterly Performance System Reviews + advisory support",
    barFill: 1,
    tags: ["Cycle resilience", "Engagement holds", "Difficult to break"]
  }];

  const [ref, seen] = useInView();
  return (
    <section className={"m-section m-journey m-journey-v5" + (seen ? " is-in" : "")} ref={ref}>
      <div className="m-container">
        <span className="m-overline">FROM DIAGNOSIS TO ONGOING ADVISORY</span>
        <h2 className="m-h2">
          A structured progression — and the pattern of change it produces.
        </h2>
        <p className="m-section-intro">
          Engagements move through four stages. The first two replace assumption with evidence. The second two are where the pattern of change becomes visible — first in delivery, then in capacity.
        </p>

        <div className="m-journey-track" aria-hidden>
          <span className="m-journey-track-line" />
        </div>
        <ol className="m-journey-grid">
          {stops.map((s, i) =>
          <li key={i} className="m-journey-stop" style={{ "--m-i": i }}>
              <div className="m-journey-dot" aria-hidden />
              <div className="m-journey-num"><Counter to={i + 1} pad={2} /></div>
              <span className="m-journey-window">{s.window}</span>
              <h3 className="m-journey-label">{s.label}</h3>
              <div className="m-journey-bar" aria-hidden>
                <span className="m-journey-bar-fill" style={{ "--fill": s.barFill }} />
              </div>
              <p className="m-journey-body">{s.body}</p>
              {s.deliverable &&
            <div className="m-journey-deliverable">
                  <span className="m-journey-deliverable-label">Deliverable</span>
                  <span className="m-journey-deliverable-value">{s.deliverable}</span>
                </div>
            }
              {s.tags.length > 0 &&
            <ul className="m-journey-tags">
                  {s.tags.map((t, j) => <li key={j}>{t}</li>)}
                </ul>
            }
            </li>
          )}
        </ol>
      </div>
    </section>);

};

/* =====================================================================
   08 — CLOSING CTA
   ===================================================================== */
const M_ClosingCTA = () =>
<section className="m-section m-cta m-cta-v5">
    <div className="m-cta-bg" aria-hidden>
      <span className="m-bloom m-bloom-cta-1" />
      <span className="m-bloom m-bloom-cta-2" />
    </div>
    <div className="m-container m-cta-inner">
      <h2 className="m-cta-h">
        If the methodology resonates, a direct conversation is the most useful starting point.
      </h2>
      <div className="m-cta-primary-row">
        <a href="#" className="m-btn m-btn-primary m-btn-shine">
          <span>Start a Conversation</span>
          <span className="m-btn-arrow" aria-hidden>→</span>
        </a>
      </div>
      <p className="m-cta-supporting">
        Prefer to start with the diagnostic? The PSL Performance Assessment takes around 7 minutes and delivers a structured report directly to your inbox.
      </p>
      <div className="m-cta-secondary-row">
        <a href="#" className="m-btn m-btn-secondary">
          <span>Take the Performance Assessment</span>
          <span className="m-btn-arrow" aria-hidden>→</span>
        </a>
      </div>
    </div>
  </section>;


const M_Footer = () =>
<footer className="m-footer">
    <div className="m-container">
      <div className="m-footer-top">
        <div className="m-footer-brand">
          <img src="assets/logos/PSL-Logo-Negative.svg" alt="Performance Systems Lab" className="m-footer-logo" />
          <p className="m-footer-tag">
            PSL helps leaders, teams, and organisations design the structural conditions that allow consistent execution when pressure is sustained.
          </p>
        </div>
        <nav className="m-footer-nav" aria-label="Footer">
          <a href="#">Home</a>
          <a href="#">Method</a>
          <a href="#">Teams</a>
          <a href="#">Individuals</a>
          <a href="#">About</a>
        </nav>
      </div>
      <div className="m-footer-bottom">
        <span>© 2026 Performance Systems Lab™. All rights reserved.</span>
        <div className="m-footer-legal">
          <a href="#">Terms</a>
          <a href="#">Privacy</a>
        </div>
      </div>
    </div>
  </footer>;


const M_Nav = () => {
  const links = [
  { id: "home", label: "Home" },
  { id: "method", label: "Method" },
  { id: "teams", label: "Teams" },
  { id: "individuals", label: "Individuals" }];

  return (
    <nav className="m-nav">
      <div className="m-container m-nav-inner">
        <a href="#" className="m-nav-logo" aria-label="Performance Systems Lab home">
          <img src="assets/logos/PSL-Logo-Header.svg" alt="Performance Systems Lab" />
        </a>
        <div className="m-nav-links">
          {links.map((l) =>
          <a key={l.id} href="#" className={"m-nav-link" + (l.id === "method" ? " active" : "")}>
              {l.label}
            </a>
          )}
          <a href="#" className="m-nav-cta">Diagnostic</a>
        </div>
      </div>
    </nav>);

};

/* =====================================================================
   SECTION BRIDGES — narrative spine connecting Origins → System →
   Practice Areas → Sources → Insight → Engagement.
   Each step has its own brand-palette colour.
   ===================================================================== */
const M_BRIDGE_TONES = {
  1: { bg: "linear-gradient(135deg, #312E81 0%, #4338CA 100%)", glow: "rgba(67,56,202,0.22)", accent: "#4338CA" },     // Indigo deep — Origins
  2: { bg: "linear-gradient(135deg, #6D28D9 0%, #A78BFA 100%)", glow: "rgba(124,58,237,0.28)", accent: "#8936FF" },     // Violet — Structure (Identity ring)
  3: { bg: "linear-gradient(135deg, #0F766E 0%, #2EE0B0 100%)", glow: "rgba(46,224,176,0.26)", accent: "#0F766E" },     // Teal — Application (Execution ring)
  4: { bg: "linear-gradient(135deg, #4338CA 0%, #6366F1 100%)", glow: "rgba(99,102,241,0.26)", accent: "#4F46E5" },     // Electric blue — Foundations (Capacity ring)
  5: { bg: "linear-gradient(135deg, #1F4DD8 0%, #4646FF 100%)", glow: "rgba(31,77,216,0.28)", accent: "#1F4DD8" },     // Brand blue — Worked example
  6: { bg: "linear-gradient(135deg, #0F766E 0%, #14B89A 100%)", glow: "rgba(20,184,154,0.28)", accent: "#14B89A" }      // Brand teal — Engagement / action
};

const M_Bridge = ({ step, total = 6, from, to, body }) => {
  const stepStr = String(step).padStart(2, "0");
  const t = M_BRIDGE_TONES[step] || M_BRIDGE_TONES[1];
  // Minimal connector — keeps the #m-bridge-XX anchor so the sticky step-strip
  // still tracks scroll position, but drops the heavy labelled bridge (the
  // strip already shows "02 · ORIGINS → STRUCTURE", so repeating it inline
  // read as a course-module gimmick). A quiet centred dot + hairlines.
  return (
    <div id={`m-bridge-${stepStr}`} className="m-bridge" data-step={stepStr}>
      <style>{`
        .m-bridge {
          padding: 30px 0;
          display: flex; align-items: center; justify-content: center;
          scroll-margin-top: 80px;
        }
        .m-bridge-mark {
          position: relative;
          display: inline-flex; align-items: center; justify-content: center;
          width: 7px; height: 7px; border-radius: 50%;
        }
        .m-bridge-mark::before,
        .m-bridge-mark::after {
          content: "";
          position: absolute; top: 50%;
          width: 90px; height: 1px;
        }
        .m-bridge-mark::before {
          right: 14px;
          background: linear-gradient(90deg, transparent, rgba(13,0,66,0.16));
        }
        .m-bridge-mark::after {
          left: 14px;
          background: linear-gradient(90deg, rgba(13,0,66,0.16), transparent);
        }
        @media (max-width: 760px) {
          .m-bridge { padding: 22px 0; }
          .m-bridge-mark::before, .m-bridge-mark::after { width: 56px; }
        }
      `}</style>
      <span className="m-bridge-mark" aria-hidden style={{ background: t.accent }} />
    </div>
  );
};

/* =====================================================================
   STEP STRIP — static progression bar showing the current narrative step.
   Sticks under the nav, updates as you scroll past each bridge.
   ===================================================================== */
const M_StepStrip = () => {
  const [active, setActive] = React.useState(-1);

  React.useEffect(() => {
    const onScroll = () => {
      const triggerY = 120;
      let current = -1;
      M_SECTIONS.forEach((sec, i) => {
        const el = document.getElementById(sec.id);
        if (el && el.getBoundingClientRect().top <= triggerY) current = i;
      });
      const cta = document.querySelector(".m-cta");
      if (cta && cta.getBoundingClientRect().top <= triggerY + 60) current = -1;
      setActive(current);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <nav className={"m-snav" + (active >= 0 ? " is-on" : "")} aria-label="On this page">
      <style>{`
        .m-snav {
          position: sticky; top: 54px; z-index: 40;
          background: rgba(255,255,255,0.94);
          backdrop-filter: saturate(160%) blur(12px);
          -webkit-backdrop-filter: saturate(160%) blur(12px);
          border-bottom: 1px solid rgba(13,0,66,0.07);
          transform: translateY(-100%); opacity: 0; pointer-events: none;
          transition: transform 300ms ease, opacity 240ms ease;
        }
        .m-snav.is-on { transform: translateY(0); opacity: 1; pointer-events: auto; }
        .m-snav-inner {
          max-width: 1200px; margin: 0 auto; padding: 0 32px;
          display: flex; align-items: center; gap: 20px;
          overflow-x: auto; scrollbar-width: none;
        }
        .m-snav-inner::-webkit-scrollbar { display: none; }
        .m-snav-eyebrow {
          flex-shrink: 0;
          font-size: 10px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
          color: rgba(13,0,66,0.4);
        }
        .m-snav-list {
          list-style: none; margin: 0; padding: 0;
          display: flex; align-items: stretch; gap: 2px; flex: 1;
        }
        .m-snav-link {
          appearance: none; background: none; border: none; cursor: pointer;
          font-family: "Mona Sans", sans-serif;
          display: inline-flex; align-items: center; gap: 7px;
          padding: 13px 12px; white-space: nowrap;
          font-size: 13px; font-weight: 600; color: rgba(13,0,66,0.55);
          border-bottom: 2px solid transparent;
          transition: color 0.18s ease, border-color 0.18s ease;
        }
        .m-snav-link:hover { color: #1F4DD8; }
        .m-snav-num {
          font-size: 10px; font-weight: 700; letter-spacing: 0.04em;
          color: rgba(13,0,66,0.3); font-variant-numeric: tabular-nums;
        }
        .m-snav-link.is-current { color: #1F4DD8; border-bottom-color: #1F4DD8; }
        .m-snav-link.is-current .m-snav-num { color: #1F4DD8; }
        @media (max-width: 760px) {
          .m-snav-inner { padding: 0 16px; gap: 12px; }
          .m-snav-eyebrow { display: none; }
          .m-snav-link { padding: 12px 9px; font-size: 12.5px; }
        }
      `}</style>
      <div className="m-snav-inner">
        <span className="m-snav-eyebrow">The method</span>
        <ol className="m-snav-list">
          {M_SECTIONS.map((sec, i) =>
          <li key={sec.id}>
              <button
                className={"m-snav-link" + (i === active ? " is-current" : "")}
                onClick={() => M_jumpTo(sec.id)}
                aria-current={i === active ? "true" : undefined}>
                <span className="m-snav-num">{String(i + 1).padStart(2, "0")}</span>
                {sec.label}
              </button>
            </li>
          )}
        </ol>
      </div>
    </nav>
  );
};

const M_JourneyV7 = () => {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (window.__pjJourney && ref.current && !ref.current.dataset.rendered) {
      ref.current.dataset.rendered = "1";
      window.__pjJourney.render(ref.current);
    }
  }, []);
  // id keeps the sticky step-strip's step-06 anchor; light-grey bg matches the
  // old journey band so the dark Insight transitions onto a defined surface.
  return <div id="sec-engagement" ref={ref} style={{ background: "#F4F4F4", scrollMarginTop: 80 }} />;
};

const Method = () =>
<div className="psl-method psl-method-v5" data-screen-label="01 PSL Method Page">
    <PSLNav theme="light" active="method" />
    <M_StepStrip />
    <M_Hero />
    <M_Origins />
    <M_System />
    <M_PracticeAreas />
    <M_Sources />
    <M_Insight />
    <M_PartnersNetwork />
    <M_JourneyV7 />
    <M_ClosingCTA />
    <PSLFooter />
  </div>;


Object.assign(window, { Method });