const { useState, useEffect } = React;

/* -------- Brand mark -------- */
const Logo = ({ size = 22, dark = false }) => (
  <span className="brand">
    <svg width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
      <circle cx="12" cy="12" r="9.5" fill="none" stroke="#8B5CF6" strokeWidth="2.2" strokeLinecap="round" strokeDasharray="14.14 4.71" />
    </svg>
    <span>
      <span className="soft" style={dark ? { color: "hsl(200 10% 65%)" } : null}>Portal</span>
      <span className="strong" style={dark ? { color: "hsl(42 22% 96%)" } : null}>Pulse</span>
    </span>
  </span>
);

const Btn = ({ variant = "primary", children, href = "#", ...rest }) => (
  <a href={href} className={`btn btn-${variant}`} {...rest}>
    {children}
    <span className="arrow" aria-hidden="true">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
        <path d="M5 12h14M13 5l7 7-7 7" />
      </svg>
    </span>
  </a>
);

const Tick = () => (
  <span className="tick" aria-hidden="true">
    <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
      <polyline points="4 12 10 18 20 6" />
    </svg>
  </span>
);

const Assurance = ({ items }) => (
  <div className="assurance">
    {items.map((t, i) => (
      <span key={i} style={{ display: "inline-flex", alignItems: "center" }}><Tick />{t}</span>
    ))}
  </div>
);

const SectionMarker = ({ num, label }) => (
  <div className="section-marker">
    <span className="num">{num}</span><span>{label}</span><span className="rule" />
  </div>
);

/* ===========================================================
   HERO DIAGRAM — "The Portal Listener"
   A mechanical/operational schematic. Concentric scopes of
   what's being observed, with a dashed purple pulse-ring
   as the agent boundary. Small mono labels around the ring.
   =========================================================== */
const PortalListener = () => {
  const ringNodes = [
    { a: -70, label: "workflows" },
    { a: -20, label: "pipelines" },
    { a: 30, label: "properties" },
    { a: 80, label: "reports" },
    { a: 130, label: "users" },
    { a: 180, label: "lifecycle" },
    { a: 225, label: "deals" },
    { a: 280, label: "contacts" },
  ];
  const teal = "hsl(var(--pp-dark-teal))";
  const rad = (deg) => (deg * Math.PI) / 180;

  return (
    <svg className="portal-listener" viewBox="0 0 480 480" width="100%" aria-hidden="true">
      {/* Outer very faint radial grid */}
      {[80, 140, 200].map((r) => (
        <circle key={r} cx="240" cy="240" r={r} fill="none" stroke="hsl(200 15% 80%)" strokeWidth="0.6" opacity="0.5" />
      ))}

      {/* Dashed purple pulse ring — the agent boundary */}
      <circle cx="240" cy="240" r="210" fill="none" stroke="#8B5CF6" strokeWidth="1.2" strokeLinecap="round" strokeDasharray="16 6" opacity="0.75">
        <animateTransform attributeName="transform" type="rotate" from="0 240 240" to="360 240 240" dur="80s" repeatCount="indefinite" />
      </circle>

      {/* 231 tiny radial ticks — the checks */}
      {Array.from({ length: 231 }).map((_, i) => {
        const angle = (i / 231) * Math.PI * 2 - Math.PI / 2;
        const r1 = 218, r2 = 224;
        const x1 = 240 + Math.cos(angle) * r1;
        const y1 = 240 + Math.sin(angle) * r1;
        const x2 = 240 + Math.cos(angle) * r2;
        const y2 = 240 + Math.sin(angle) * r2;
        const highlight = i % 17 === 0;
        return (
          <line key={i} x1={x1} y1={y1} x2={x2} y2={y2}
                stroke={highlight ? teal : "hsl(200 15% 65%)"}
                strokeWidth={highlight ? 1.4 : 0.7}
                opacity={highlight ? 0.9 : 0.45} />
        );
      })}

      {/* Labels just inside the ring */}
      {ringNodes.map((n) => {
        const r = 170;
        const x = 240 + Math.cos(rad(n.a)) * r;
        const y = 240 + Math.sin(rad(n.a)) * r;
        const tx = 240 + Math.cos(rad(n.a)) * (r - 8);
        const ty = 240 + Math.sin(rad(n.a)) * (r - 8);
        return (
          <g key={n.label}>
            <circle cx={x} cy={y} r="2.2" fill={teal} />
            <text x={tx} y={ty}
                  fontFamily="IBM Plex Mono, monospace"
                  fontSize="10"
                  fill="hsl(var(--pp-ink))"
                  textAnchor={Math.cos(rad(n.a)) < -0.2 ? "end" : Math.cos(rad(n.a)) > 0.2 ? "start" : "middle"}
                  alignmentBaseline="middle"
                  opacity="0.8">
              {n.label}
            </text>
          </g>
        );
      })}

      {/* Signal lines — things being "heard" */}
      {ringNodes.map((n, i) => {
        const r = 170;
        const x = 240 + Math.cos(rad(n.a)) * r;
        const y = 240 + Math.sin(rad(n.a)) * r;
        return (
          <line key={i} x1="240" y1="240" x2={x} y2={y}
                stroke={teal} strokeWidth="0.6" opacity="0.25" />
        );
      })}

      {/* Center core */}
      <circle cx="240" cy="240" r="42" fill="hsl(var(--pp-paper))" />
      <circle cx="240" cy="240" r="42" fill="none" stroke={teal} strokeWidth="1.4" />
      <circle cx="240" cy="240" r="6" fill={teal}>
        <animate attributeName="r" values="5;9;5" dur="2.4s" repeatCount="indefinite" />
        <animate attributeName="opacity" values="1;0.3;1" dur="2.4s" repeatCount="indefinite" />
      </circle>
      <text x="240" y="264" textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="9" fill="hsl(var(--pp-quiet))" letterSpacing="0.1em">
        LISTENING
      </text>

      {/* Corner annotations — like a scientific diagram */}
      <g fontFamily="IBM Plex Mono, monospace" fontSize="9" fill="hsl(var(--pp-quiet))">
        <text x="12" y="18">FIG. 01</text>
        <text x="12" y="32" opacity="0.75">Portal Listener</text>
        <text x="468" y="18" textAnchor="end">READ-ONLY</text>
        <text x="468" y="32" textAnchor="end" opacity="0.75">231 checks · day 04</text>
        <text x="12" y="470" opacity="0.75">scope boundary ← pulse ring</text>
        <text x="468" y="470" textAnchor="end" opacity="0.75">signal → findings</text>
      </g>
    </svg>
  );
};

/* ===========================================================
   PROBLEM CHARTS — each explains the pain without words
   =========================================================== */

/* Forecast fan — actual line + widening band of maybes */
const ChartForecast = () => {
  const ink = "hsl(var(--pp-ink))";
  const teal = "hsl(var(--pp-dark-teal))";
  return (
    <svg viewBox="0 0 320 140" width="100%" className="problem-chart" aria-hidden="true">
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="6" y="14">QTR FORECAST — submitted vs. where it actually landed</text>
      </g>
      {/* grid */}
      <line x1="20" y1="110" x2="300" y2="110" stroke="hsl(200 15% 80%)" strokeWidth="0.5" />
      {/* actual submitted line */}
      <path d="M20 80 L80 70 L140 72 L200 60 L260 55 L300 52" fill="none" stroke={ink} strokeWidth="1.4" />
      {/* fan of maybes (what could have happened) */}
      <path d="M200 60 L260 30 L300 18 L300 90 L260 85 L200 60 Z" fill={teal} opacity="0.12" />
      <path d="M200 60 L260 30 L300 18" fill="none" stroke={teal} strokeWidth="0.6" strokeDasharray="2 2" opacity="0.7" />
      <path d="M200 60 L260 85 L300 90" fill="none" stroke={teal} strokeWidth="0.6" strokeDasharray="2 2" opacity="0.7" />
      {/* where it actually landed */}
      <circle cx="300" cy="75" r="3" fill={teal} />
      <text x="296" y="94" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={teal} textAnchor="end">landed</text>
      {/* labels */}
      <g fontFamily="IBM Plex Mono, monospace" fontSize="7" fill="hsl(var(--pp-quiet))">
        <text x="20" y="128">W1</text><text x="80" y="128">W4</text><text x="140" y="128">W7</text>
        <text x="200" y="128">W10</text><text x="260" y="128">W12</text><text x="296" y="128" textAnchor="end">close</text>
      </g>
      <text x="144" y="34" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={ink} opacity="0.75">no one could say why</text>
    </svg>
  );
};

/* Drift — workflow firing count, one rail quietly diverging */
const ChartDrift = () => {
  const ink = "hsl(var(--pp-ink))";
  const teal = "hsl(var(--pp-dark-teal))";
  return (
    <svg viewBox="0 0 320 140" width="100%" className="problem-chart" aria-hidden="true">
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="6" y="14">WORKFLOW — firing count, 6 months</text>
      </g>
      {/* baseline */}
      <path d="M20 70 L60 72 L100 70 L140 71 L180 70 L220 72 L260 71 L300 70" fill="none" stroke={ink} strokeWidth="1.2" />
      {/* drifting rail (another workflow, silently climbing) */}
      <path d="M20 70 L60 68 L100 66 L140 62 L180 56 L220 48 L260 38 L300 26" fill="none" stroke={teal} strokeWidth="1.2" strokeDasharray="3 2" />
      {/* dots at ends */}
      <circle cx="300" cy="70" r="2.4" fill={ink} />
      <circle cx="300" cy="26" r="2.4" fill={teal} />
      {/* annotation */}
      <line x1="260" y1="38" x2="200" y2="95" stroke={teal} strokeWidth="0.5" opacity="0.7" />
      <text x="200" y="108" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={teal}>fires on a property</text>
      <text x="200" y="118" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={teal}>that no longer exists</text>
      <g fontFamily="IBM Plex Mono, monospace" fontSize="7" fill="hsl(var(--pp-quiet))">
        <text x="20" y="128">JAN</text><text x="100" y="128">MAR</text><text x="180" y="128">MAY</text><text x="296" y="128" textAnchor="end">NOW</text>
      </g>
    </svg>
  );
};

/* Adoption — dot matrix of reps, most green, a block of muted */
const ChartAdoption = () => {
  const ink = "hsl(var(--pp-ink))";
  const teal = "hsl(var(--pp-dark-teal))";
  const cols = 20, rows = 7;
  const dots = [];
  for (let r = 0; r < rows; r++) {
    for (let c = 0; c < cols; c++) {
      const idx = r * cols + c;
      // A contiguous patch on the right-bottom have "invented their own taxonomy"
      const off = (r >= 3 && c >= 11) || (r === 2 && c >= 16);
      dots.push({ x: 24 + c * 13, y: 40 + r * 12, off, idx });
    }
  }
  return (
    <svg viewBox="0 0 320 140" width="100%" className="problem-chart" aria-hidden="true">
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="6" y="14">ADOPTION — 140 reps, by whether they use the canonical taxonomy</text>
      </g>
      {dots.map((d) => (
        <circle key={d.idx} cx={d.x} cy={d.y} r={d.off ? 2.8 : 2.2}
                fill={d.off ? "none" : teal}
                stroke={d.off ? ink : "none"}
                strokeWidth={d.off ? 1 : 0}
                opacity={d.off ? 0.7 : 0.85} />
      ))}
      <text x="314" y="134" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={ink} textAnchor="end" opacity="0.75">
        ⊙ invented their own
      </text>
      <text x="6" y="134" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={teal}>● canonical</text>
    </svg>
  );
};

/* ===========================================================
   TRUST JOURNEY — a single horizontal curve, 12 weeks.
   Beats hang off it as short labels. Week 8 dips then recovers.
   =========================================================== */
const TrustJourney = () => {
  const teal = "hsl(var(--pp-dark-teal))";
  const ink = "hsl(var(--pp-ink))";
  const purple = "#8B5CF6";

  // The trust curve — starts low, climbs, dips at wk8, recovers higher.
  const weeks = [
    { w: 1, t: "connect", x: 60, y: 170, client: "read-only access" },
    { w: 2, t: "first pulse", x: 160, y: 150, client: "3 findings surfaced" },
    { w: 3, t: "approve play", x: 260, y: 128, client: "clean slate signed" },
    { w: 5, t: "delegate", x: 400, y: 102, client: "scope, not line items" },
    { w: 8, t: "the moment", x: 560, y: 148, client: "a workflow misfires", highlight: true },
    { w: 9, t: "recovery", x: 640, y: 96, client: "reverted · explained" },
    { w: 12, t: "ops review", x: 820, y: 60, client: "evidence · not vibes" },
  ];

  const pathD = "M 40 188 "
    + "C 110 186, 140 158, 160 150 "
    + "S 240 132, 260 128 "
    + "S 360 108, 400 102 "
    + "S 500 90, 540 115 "
    + "C 560 138, 560 148, 560 148 "
    + "C 590 130, 620 105, 640 96 "
    + "S 760 68, 820 60";

  return (
    <div className="journey-wrap">
      <svg viewBox="0 0 880 300" width="100%" className="journey-svg" aria-hidden="true">
        {/* Grid — horizontal trust bands */}
        <line x1="40" y1="60"  x2="860" y2="60"  stroke="hsl(200 15% 80%)" strokeWidth="0.5" strokeDasharray="2 4" />
        <line x1="40" y1="120" x2="860" y2="120" stroke="hsl(200 15% 85%)" strokeWidth="0.5" strokeDasharray="2 4" />
        <line x1="40" y1="188" x2="860" y2="188" stroke="hsl(200 15% 85%)" strokeWidth="0.5" strokeDasharray="2 4" />

        <g fontFamily="IBM Plex Mono, monospace" fontSize="9" fill="hsl(var(--pp-quiet))">
          <text x="8" y="62">high</text>
          <text x="8" y="122">↑ trust</text>
          <text x="8" y="192">low</text>
        </g>

        {/* The curve — soft tint under it */}
        <path d={`${pathD} L 820 260 L 40 260 Z`} fill={teal} opacity="0.06" />
        <path d={pathD} fill="none" stroke={teal} strokeWidth="1.8" strokeLinecap="round" />

        {/* Week axis ticks */}
        {[1,2,3,4,5,6,7,8,9,10,11,12].map((w) => {
          const x = 40 + ((w - 1) / 11) * 820;
          return (
            <g key={w}>
              <line x1={x} y1="258" x2={x} y2="264" stroke="hsl(200 15% 70%)" strokeWidth="0.6" />
              <text x={x} y="278" fontFamily="IBM Plex Mono, monospace" fontSize="9" fill="hsl(var(--pp-quiet))" textAnchor="middle">
                W{w}
              </text>
            </g>
          );
        })}

        {/* Beat markers */}
        {weeks.map((m) => (
          <g key={m.w}>
            {/* drop line from curve down to axis */}
            <line x1={m.x} y1={m.y} x2={m.x} y2="258" stroke={m.highlight ? teal : "hsl(200 15% 70%)"} strokeWidth="0.6" strokeDasharray={m.highlight ? "none" : "2 3"} opacity={m.highlight ? 0.8 : 0.5} />
            {/* node */}
            <circle cx={m.x} cy={m.y} r={m.highlight ? 6 : 4} fill={m.highlight ? teal : "hsl(var(--pp-paper))"} stroke={teal} strokeWidth={m.highlight ? 1.6 : 1.4} />
            {m.highlight && (
              <circle cx={m.x} cy={m.y} r="12" fill="none" stroke={teal} strokeWidth="1" opacity="0.3">
                <animate attributeName="r" values="10;16;10" dur="2.5s" repeatCount="indefinite" />
                <animate attributeName="opacity" values="0.5;0;0.5" dur="2.5s" repeatCount="indefinite" />
              </circle>
            )}
            {/* label above node */}
            <text x={m.x} y={m.y - 14} fontFamily="Manrope, sans-serif" fontSize="12" fontWeight="600" fill={ink} textAnchor="middle">
              {m.t}
            </text>
            <text x={m.x} y={m.y - 28} fontFamily="IBM Plex Mono, monospace" fontSize="9" fill={m.highlight ? teal : "hsl(var(--pp-quiet))"} textAnchor="middle" letterSpacing="0.05em">
              WEEK {m.w}
            </text>
          </g>
        ))}

        {/* Week 8 annotation callout */}
        <g>
          <path d="M 540 148 Q 520 172, 500 200" fill="none" stroke={teal} strokeWidth="0.8" strokeDasharray="2 2" />
          <rect x="350" y="200" width="170" height="48" rx="6" fill="hsl(var(--pp-paper))" stroke={teal} strokeWidth="0.8" />
          <text x="360" y="216" fontFamily="IBM Plex Mono, monospace" fontSize="9" fill={teal} fontWeight="600" letterSpacing="0.08em">THE MOMENT OF TRUTH</text>
          <text x="360" y="230" fontFamily="Manrope, sans-serif" fontSize="11" fontWeight="600" fill={ink}>a failure happens.</text>
          <text x="360" y="242" fontFamily="Manrope, sans-serif" fontSize="11" fill={ink} opacity="0.7">the agent tells you first.</text>
        </g>

        {/* Legend */}
        <g fontFamily="IBM Plex Mono, monospace" fontSize="9" fill="hsl(var(--pp-quiet))">
          <text x="40" y="20">FIG. 02 — Trust, as earned over twelve weeks.</text>
          <text x="860" y="20" textAnchor="end">y: client confidence · x: weeks since connect</text>
        </g>
      </svg>
    </div>
  );
};

/* ===========================================================
   PLAY DIAGRAMS — tiny operational schematics per play
   =========================================================== */

/* Clean Slate — a cluster with some nodes being pruned */
const PlayDiagramCleanSlate = () => {
  const teal = "hsl(var(--pp-dark-teal))";
  const ink = "hsl(var(--pp-ink))";
  return (
    <svg viewBox="0 0 320 130" width="100%" className="play-diagram" aria-hidden="true">
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="0" y="10">BEFORE — 47 active</text>
        <text x="320" y="10" textAnchor="end">AFTER — 28 active · 19 retired</text>
      </g>
      {/* grid of 47 dots, right side prunes ~19 */}
      {Array.from({ length: 47 }).map((_, i) => {
        const col = i % 12;
        const row = Math.floor(i / 12);
        const xL = 6 + col * 10;
        const y = 30 + row * 16;
        const xR = 180 + col * 10;
        const pruned = i % 7 === 3 || i % 11 === 5 || i === 2 || i === 14;
        return (
          <g key={i}>
            <circle cx={xL} cy={y} r="3" fill={teal} opacity="0.85" />
            {pruned ? (
              <g>
                <line x1={xR - 3} y1={y - 3} x2={xR + 3} y2={y + 3} stroke={ink} strokeWidth="0.8" opacity="0.35" />
                <line x1={xR + 3} y1={y - 3} x2={xR - 3} y2={y + 3} stroke={ink} strokeWidth="0.8" opacity="0.35" />
              </g>
            ) : (
              <circle cx={xR} cy={y} r="3" fill={teal} opacity="0.85" />
            )}
          </g>
        );
      })}
      <path d="M 140 65 L 170 65" stroke={ink} strokeWidth="0.8" />
      <path d="M 165 61 L 170 65 L 165 69" fill="none" stroke={ink} strokeWidth="0.8" />
    </svg>
  );
};

/* Pipeline Integrity — bent rail becomes a straightened one */
const PlayDiagramPipeline = () => {
  const teal = "hsl(var(--pp-dark-teal))";
  const ink = "hsl(var(--pp-ink))";
  return (
    <svg viewBox="0 0 320 130" width="100%" className="play-diagram" aria-hidden="true">
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="0" y="10">BEFORE — stages mean different things per team</text>
      </g>
      {/* 3 bent rails (different teams) */}
      <path d="M 6 36 Q 60 26, 110 42 T 220 34 T 314 40" fill="none" stroke={ink} strokeWidth="1.1" opacity="0.7" />
      <path d="M 6 48 Q 60 68, 110 50 T 220 62 T 314 48" fill="none" stroke={ink} strokeWidth="1.1" opacity="0.4" strokeDasharray="3 2" />
      <path d="M 6 60 Q 60 46, 110 68 T 220 50 T 314 56" fill="none" stroke={ink} strokeWidth="1.1" opacity="0.55" strokeDasharray="2 2" />
      {/* divider */}
      <line x1="6" y1="82" x2="314" y2="82" stroke="hsl(200 15% 80%)" strokeWidth="0.5" strokeDasharray="2 2" />
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="0" y="96">AFTER — one taxonomy, one forecast</text>
      </g>
      {/* single straight rail with stage ticks */}
      <line x1="6" y1="114" x2="314" y2="114" stroke={teal} strokeWidth="1.6" strokeLinecap="round" />
      {[6, 82, 158, 234, 314].map((x, i) => (
        <g key={i}>
          <circle cx={x} cy="114" r="3" fill={teal} />
          <text x={x} y="126" fontFamily="IBM Plex Mono, monospace" fontSize="7" fill={teal} textAnchor="middle" opacity="0.75">
            {["new","qual","demo","nego","won"][i]}
          </text>
        </g>
      ))}
    </svg>
  );
};

/* Lead Source — tangled many → organized few */
const PlayDiagramLeadSource = () => {
  const teal = "hsl(var(--pp-dark-teal))";
  const ink = "hsl(var(--pp-ink))";
  // 14 tangled sources on left, merged to 5 on right
  const leftSources = Array.from({ length: 14 }).map((_, i) => ({ x: 14, y: 20 + i * 7 }));
  const rightSources = Array.from({ length: 5 }).map((_, i) => ({ x: 300, y: 30 + i * 18 }));
  return (
    <svg viewBox="0 0 320 130" width="100%" className="play-diagram" aria-hidden="true">
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="0" y="10">BEFORE — 14 overlapping source tags</text>
        <text x="320" y="10" textAnchor="end">AFTER — 5 canonical</text>
      </g>
      {/* tangle */}
      {leftSources.map((s, i) => {
        const target = rightSources[i % rightSources.length];
        return (
          <path key={i}
                d={`M ${s.x} ${s.y} C 120 ${s.y}, 200 ${target.y}, ${target.x} ${target.y}`}
                fill="none" stroke={ink} strokeWidth="0.6" opacity="0.35" />
        );
      })}
      {leftSources.map((s, i) => <circle key={i} cx={s.x} cy={s.y} r="2" fill={ink} opacity="0.55" />)}
      {rightSources.map((s, i) => <circle key={i} cx={s.x} cy={s.y} r="3.2" fill={teal} />)}
      {rightSources.map((s, i) => (
        <text key={i} x={s.x - 6} y={s.y + 3} fontFamily="IBM Plex Mono, monospace" fontSize="7" fill={teal} textAnchor="end">
          {["organic","paid","referral","event","outbound"][i]}
        </text>
      ))}
    </svg>
  );
};

const PLAY_DIAGRAMS = [PlayDiagramCleanSlate, PlayDiagramPipeline, PlayDiagramLeadSource];

/* ===========================================================
   PORTAL BOUNDARY — mechanical diagram for the Security col
   =========================================================== */
const PortalBoundary = () => {
  const teal = "hsl(var(--pp-dark-teal))";
  const ink = "hsl(var(--pp-ink))";
  return (
    <svg viewBox="0 0 320 180" width="100%" className="portal-boundary" aria-hidden="true">
      {/* HubSpot portal box */}
      <rect x="20" y="30" width="160" height="130" rx="6" fill="none" stroke={ink} strokeWidth="1" />
      <text x="28" y="46" fontFamily="IBM Plex Mono, monospace" fontSize="9" fill={ink}>HUBSPOT PORTAL</text>
      {/* Records inside */}
      {Array.from({ length: 24 }).map((_, i) => {
        const col = i % 6;
        const row = Math.floor(i / 6);
        return <circle key={i} cx={36 + col * 22} cy={70 + row * 18} r="2.2" fill={ink} opacity="0.45" />;
      })}

      {/* Portal Pulse box */}
      <rect x="220" y="60" width="80" height="70" rx="6" fill="none" stroke={teal} strokeWidth="1.2" />
      <text x="228" y="76" fontFamily="IBM Plex Mono, monospace" fontSize="9" fill={teal}>PORTAL PULSE</text>
      <text x="228" y="100" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={ink} opacity="0.6">· findings</text>
      <text x="228" y="112" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={ink} opacity="0.6">· metadata</text>
      <text x="228" y="124" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={ink} opacity="0.6">· profile</text>

      {/* Arrows */}
      <g>
        <line x1="180" y1="80" x2="220" y2="80" stroke={teal} strokeWidth="1" />
        <path d="M 214 76 L 220 80 L 214 84" fill="none" stroke={teal} strokeWidth="1" />
        <text x="182" y="72" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={teal}>read</text>
      </g>
      <g>
        <line x1="220" y1="110" x2="180" y2="110" stroke={ink} strokeWidth="0.8" strokeDasharray="3 3" opacity="0.6" />
        <path d="M 186 106 L 180 110 L 186 114" fill="none" stroke={ink} strokeWidth="0.8" opacity="0.6" />
        <text x="180" y="124" fontFamily="IBM Plex Mono, monospace" fontSize="8" fill={ink} textAnchor="end" opacity="0.7">approved actions</text>
      </g>

      {/* Legend */}
      <g fontFamily="IBM Plex Mono, monospace" fontSize="8" fill="hsl(var(--pp-quiet))">
        <text x="20" y="176">— your data stays in your portal</text>
      </g>
    </svg>
  );
};

Object.assign(window, {
  Logo, Btn, Assurance, SectionMarker,
  PortalListener,
  ChartForecast, ChartDrift, ChartAdoption,
  TrustJourney,
  PLAY_DIAGRAMS,
  PortalBoundary,
});
