// Postgres landing page — final content spec with alternating light/dark
// section backgrounds, inline SVG diagrams, and outcome stat boxes.

/* ============================ Reusable: contact form ============================ */
function PGContactForm({ compact }) {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [company, setCompany] = React.useState("");
  const [size, setSize] = React.useState("");
  const [msg, setMsg] = React.useState("");
  const [sent, setSent] = React.useState(false);
  const onSubmit = (e) => { e.preventDefault(); setSent(true); };
  if (sent) {
    return (
      <div className={`pg-form pg-form-sent ${compact ? "compact" : ""}`}>
        <div className="pg-form-check">
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <polyline points="20 6 9 17 4 12"/>
          </svg>
        </div>
        <div className="pg-form-thanks">Thanks, we'll be in touch within 1 business day.</div>
      </div>
    );
  }
  return (
    <form className={`pg-form ${compact ? "compact" : ""}`} onSubmit={onSubmit}>
      <div className="pg-form-head">
        <div className="pg-form-eyebrow">Talk to an engineer</div>
        <div className="pg-form-title">Tell us about your Postgres workload.</div>
      </div>
      <div className="pg-form-row">
        <label>
          <span>Name</span>
          <input type="text" required value={name} onChange={e => setName(e.target.value)} placeholder="Jamie Chen" />
        </label>
        <label>
          <span>Work email</span>
          <input type="email" required value={email} onChange={e => setEmail(e.target.value)} placeholder="jamie@company.com" />
        </label>
      </div>
      <div className="pg-form-row">
        <label>
          <span>Company</span>
          <input type="text" value={company} onChange={e => setCompany(e.target.value)} placeholder="Acme, Inc." />
        </label>
        <label>
          <span>Team size</span>
          <select value={size} onChange={e => setSize(e.target.value)}>
            <option value="">Select</option>
            <option>1–10</option>
            <option>11–50</option>
            <option>51–200</option>
            <option>201–1000</option>
            <option>1000+</option>
          </select>
        </label>
      </div>
      <label className="pg-form-msg">
        <span>What are you trying to solve?</span>
        <textarea value={msg} onChange={e => setMsg(e.target.value)} rows={3} placeholder="Concurrency, CDC, vector search, total cost..." />
      </label>
      <button type="submit" className="btn btn-velo btn-lg">Start Free Cloud Trial <ArrowR /></button>
      <div className="pg-form-foot">We will respond within 1 business day.</div>
    </form>
  );
}

/* ============================ Hero (split 2-col with form) ============================ */
function PGHero() {
  return (
    <section className="pg-hero pg-hero-split" data-screen-label="01 Hero">
      <div className="hero-bg" />
      <div className="hero-grid" />
      <div className="wrap">
        <div className="pg-hero-split-inner">
          <div className="pg-hero-l">
            <div className="pg-eyebrow">
              <span className="pg-badge">Postgres</span>
              <span>Solutions / Scaling Real-Time Analytics From PostgreSQL</span>
            </div>
            <h1 className="pg-hero-title">
              Scaling Real-Time<br/>
              Analytics From<br/>
              <span className="accent">PostgreSQL</span>
            </h1>
            <p className="pg-hero-bullet">
              <span className="pg-hero-bullet-dot" />
              Sub-second analytical queries, native CDC sync, and high concurrency on rapidly changing transactional data.
            </p>
            <div className="pg-hero-cta">
              <button className="btn btn-velo btn-lg">Start Free Cloud Trial <ArrowR /></button>
            </div>
          </div>
          <div className="pg-hero-r">
            <PGContactForm />
          </div>
        </div>
      </div>
    </section>
  );
}

/* ============================ Section: New Release (light, 2-col with wheel) ============================ */
function PGCapabilityWheel() {
  // 5 outer nodes around a central hub. Plain SVG, no animation, all blue line-art.
  const nodes = [
    { angle: -90, label: "Native Postgres CDC", icon: "sync" },
    { angle: -18, label: "Columnar Analytics",  icon: "bars" },
    { angle:  54, label: "Materialized Views",  icon: "layers" },
    { angle: 126, label: "High Concurrency",    icon: "users" },
    { angle: 198, label: "Merge-on-Write",      icon: "merge" },
  ];
  const cx = 280, cy = 240, R = 170;

  const IconFor = ({ name, x, y }) => {
    const props = { stroke: "var(--velo-blue)", strokeWidth: 1.5, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" };
    const t = (off) => `translate(${x - 10},${y - 10})`;
    if (name === "sync") return (
      <g transform={t()} {...props}>
        <path d="M4 8a6 6 0 0 1 11-3M16 12a6 6 0 0 1-11 3" />
        <polyline points="13 5 16 5 16 2" />
        <polyline points="7 15 4 15 4 18" />
      </g>
    );
    if (name === "bars") return (
      <g transform={t()} {...props}>
        <rect x="3" y="11" width="3" height="8" />
        <rect x="8.5" y="6" width="3" height="13" />
        <rect x="14" y="2" width="3" height="17" />
      </g>
    );
    if (name === "layers") return (
      <g transform={t()} {...props}>
        <polygon points="10 2 18 7 10 12 2 7" />
        <polyline points="2 12 10 17 18 12" />
        <polyline points="2 16 10 21 18 16" />
      </g>
    );
    if (name === "users") return (
      <g transform={t()} {...props}>
        <circle cx="7" cy="7" r="3" />
        <path d="M2 18a5 5 0 0 1 10 0" />
        <circle cx="14" cy="9" r="2.5" />
        <path d="M11 18a4 4 0 0 1 8 0" />
      </g>
    );
    if (name === "merge") return (
      <g transform={t()} {...props}>
        <circle cx="4" cy="4" r="2" />
        <circle cx="16" cy="4" r="2" />
        <circle cx="10" cy="18" r="2" />
        <path d="M5 6 q 0 6 5 10" />
        <path d="M15 6 q 0 6 -5 10" />
      </g>
    );
    return null;
  };

  return (
    <svg viewBox="0 0 560 480" fill="none" preserveAspectRatio="xMidYMid meet" className="pg-wheel">
      {/* outer connecting lines */}
      {nodes.map((n, i) => {
        const rad = (n.angle * Math.PI) / 180;
        const x = cx + Math.cos(rad) * R;
        const y = cy + Math.sin(rad) * R;
        // inner edge of hub roughly at 70
        const hx = cx + Math.cos(rad) * 70;
        const hy = cy + Math.sin(rad) * 70;
        return <line key={i} x1={hx} y1={hy} x2={x} y2={y} stroke="rgba(11,110,200,0.30)" strokeWidth="1" />;
      })}

      {/* central hexagon */}
      <g transform={`translate(${cx}, ${cy})`}>
        <polygon points="0,-78 67,-39 67,39 0,78 -67,39 -67,-39" fill="rgba(11,162,255,0.05)" stroke="var(--velo-blue)" strokeWidth="1.6" />
        <text textAnchor="middle" y="-12" fontFamily="ui-monospace, monospace" fontSize="10" fill="var(--velo-blue)" letterSpacing="0.14em">APACHE DORIS 4.1</text>
        <text textAnchor="middle" y="10" fontFamily="Inter, sans-serif" fontSize="13" fontWeight="700" fill="#0a60b5">Real-Time</text>
        <text textAnchor="middle" y="28" fontFamily="Inter, sans-serif" fontSize="13" fontWeight="700" fill="#0a60b5">Analytics for Postgres</text>
      </g>

      {/* outer nodes */}
      {nodes.map((n, i) => {
        const rad = (n.angle * Math.PI) / 180;
        const x = cx + Math.cos(rad) * R;
        const y = cy + Math.sin(rad) * R;
        return (
          <g key={i}>
            <circle cx={x} cy={y} r="44" fill="#fff" stroke="var(--velo-blue)" strokeWidth="1.4" />
            <IconFor name={n.icon} x={x} y={y - 12} />
            <text x={x} y={y + 16} textAnchor="middle" fontFamily="Inter, sans-serif" fontSize="10" fontWeight="600" fill="#0a60b5">
              {n.label.split(" ").map((w, j) => (
                <tspan key={j} x={x} dy={j === 0 ? 0 : 11}>{w}</tspan>
              ))}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

function PGRelease() {
  return (
    <section className="pg-section pg-release-section light" data-screen-label="02 New Release">
      <div className="wrap">
        <div className="pg-2col">
          <div className="pg-2col-text">
            <div className="pg-pill-light">
              <span className="pg-pill-dot" />
              New Release
            </div>
            <h2 className="pg-section-title">Apache Doris 4.1 Ships<br/>Native PostgreSQL CDC</h2>
            <p className="pg-section-body">
              Apache Doris 4.1 lets you sync from PostgreSQL with a single SQL statement. No external Flink cluster, Debezium, or Kafka required. Full snapshot and continuous incremental sync run inside the engine. <a className="pg-link-light">Learn more about the release <ArrowR /></a>
            </p>
            <p className="pg-section-body pg-section-body-quiet">
              Hear from teams scaling beyond Postgres on how VeloDB delivers the concurrency, freshness, and analytical speed that read replicas and pgvector cannot.
            </p>
          </div>
          <div className="pg-2col-visual pg-2col-visual-light">
            <PGCapabilityWheel />
          </div>
        </div>
      </div>
    </section>
  );
}

/* ============================ Section building blocks ============================ */
function PGOutcomeBox({ title, stats, light }) {
  return (
    <div className={`pg-outcome ${light ? "light" : ""}`}>
      <div className="pg-outcome-head">{title}</div>
      <div className="pg-outcome-stats">
        {stats.map((s, i) => (
          <div key={i} className="pg-outcome-stat">
            <div className="pg-outcome-n">{s.n}</div>
            <div className="pg-outcome-l">{s.l}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

function PGContentColumn({ headline, paragraphs, cta, outcome, light }) {
  return (
    <div className="pg-content-col">
      <h2 className={`pg-section-title ${light ? "" : "on-dark"}`}>{headline}</h2>
      {paragraphs.map((p, i) => (
        <p key={i} className={`pg-section-body ${light ? "" : "on-dark"}`}>{p}</p>
      ))}
      <a className={`pg-vp-cta ${light ? "light" : ""}`}>{cta} <ArrowR /></a>
      <PGOutcomeBox {...outcome} light={light} />
    </div>
  );
}

/* ============================ Diagrams (inline SVG) ============================ */
function PGDiagramConcurrency() {
  return (
    <svg viewBox="0 0 560 460" fill="none" preserveAspectRatio="xMidYMid meet" className="pg-diagram">
      {/* Top row: 10 analysts → Postgres (calm) */}
      <text x="20" y="32" fontSize="11" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">A — 10 ANALYSTS</text>

      <g transform="translate(20, 50)">
        {/* user dots */}
        {Array.from({ length: 10 }, (_, i) => (
          <circle key={i} cx={10 + (i * 14)} cy={14} r="5" fill="rgba(11,162,255,0.40)" stroke="var(--velo-blue)" strokeWidth="1"/>
        ))}
        {/* arrows */}
        <path d="M 75 30 L 75 56" stroke="rgba(255,255,255,0.40)" strokeWidth="1"/>
        <path d="M 71 52 L 75 56 L 79 52" stroke="rgba(255,255,255,0.40)" strokeWidth="1" fill="none"/>
        {/* postgres */}
        <rect x="0" y="62" width="240" height="48" rx="8" fill="rgba(76,175,80,0.10)" stroke="rgba(76,175,80,0.55)" strokeWidth="1.2"/>
        <text x="120" y="84" textAnchor="middle" fontSize="13" fontWeight="600" fill="#fff" fontFamily="Inter">Postgres</text>
        <text x="120" y="100" textAnchor="middle" fontSize="10" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">healthy · low concurrency</text>
        <circle cx="220" cy="86" r="4" fill="#25D366"/>
      </g>

      {/* Divider */}
      <line x1="20" y1="190" x2="540" y2="190" stroke="rgba(255,255,255,0.10)" strokeDasharray="3 3"/>

      {/* Bottom row */}
      <text x="20" y="220" fontSize="11" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">B — 10,000 DASHBOARD USERS</text>

      {/* user grid: 10x10 dots */}
      <g transform="translate(20, 240)">
        {Array.from({ length: 50 }, (_, i) => (
          <circle key={i} cx={(i % 10) * 12} cy={Math.floor(i / 10) * 12} r="3" fill="rgba(255,255,255,0.30)"/>
        ))}
        <text x="135" y="30" fontSize="10" fill="rgba(255,255,255,0.55)" fontFamily="ui-monospace,monospace">10,000 concurrent</text>
      </g>

      {/* arrows splitting */}
      <path d="M 70 320 Q 100 360 140 380" stroke="rgba(76,175,80,0.50)" strokeWidth="1.2" fill="none"/>
      <text x="80" y="346" fontSize="9" fill="rgba(76,175,80,0.80)" fontFamily="ui-monospace,monospace">writes</text>
      <path d="M 70 320 Q 220 360 320 380" stroke="var(--velo-cyan)" strokeWidth="1.2" fill="none"/>
      <text x="210" y="358" fontSize="9" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace">analytics</text>

      {/* Postgres (transactional, healthy) */}
      <g transform="translate(90, 380)">
        <rect width="120" height="44" rx="6" fill="rgba(76,175,80,0.10)" stroke="rgba(76,175,80,0.55)"/>
        <text x="60" y="20" textAnchor="middle" fontSize="11" fontWeight="600" fill="#fff" fontFamily="Inter">Postgres</text>
        <text x="60" y="34" textAnchor="middle" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">transactions only</text>
        <circle cx="106" cy="22" r="3" fill="#25D366"/>
      </g>

      {/* VeloDB (analytics) */}
      <g transform="translate(280, 380)">
        <rect width="240" height="44" rx="6" fill="rgba(11,162,255,0.15)" stroke="var(--velo-cyan)" strokeWidth="1.5"/>
        <text x="120" y="20" textAnchor="middle" fontSize="11" fontWeight="600" fill="#fff" fontFamily="Inter">VeloDB · analytical reads</text>
        <text x="120" y="34" textAnchor="middle" fontSize="9" fill="rgba(26,236,255,0.80)" fontFamily="ui-monospace,monospace">10,000 QPS · 150ms p99 · 4x less CPU</text>
        <circle cx="226" cy="22" r="3" fill="#25D366"/>
      </g>

      {/* outputs */}
      <text x="280" y="442" fontSize="9" fill="rgba(255,255,255,0.55)" fontFamily="ui-monospace,monospace">→ dashboards</text>
      <text x="370" y="442" fontSize="9" fill="rgba(255,255,255,0.55)" fontFamily="ui-monospace,monospace">→ APIs</text>
      <text x="430" y="442" fontSize="9" fill="rgba(255,255,255,0.55)" fontFamily="ui-monospace,monospace">→ portals</text>
    </svg>
  );
}

function PGDiagramFreshness() {
  return (
    <svg viewBox="0 0 560 460" fill="none" preserveAspectRatio="xMidYMid meet" className="pg-diagram light">
      {/* Top: Traditional Pipeline */}
      <text x="20" y="32" fontSize="11" fill="#FF6B7E" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">A — TRADITIONAL CDC PIPELINE</text>
      <g transform="translate(20, 50)" opacity="0.55">
        {/* boxes */}
        {[
          { x: 0,   l: "Postgres",  s: "source" },
          { x: 95,  l: "Debezium",  s: "capture" },
          { x: 190, l: "Kafka",     s: "buffer" },
          { x: 285, l: "Flink",     s: "transform" },
          { x: 380, l: "OLAP",      s: "load" },
        ].map((b, i) => (
          <g key={b.l} transform={`translate(${b.x}, 0)`}>
            <rect width="80" height="40" rx="5" fill="#f4f4f8" stroke="#9aa3b2"/>
            <text x="40" y="18" textAnchor="middle" fontSize="10" fontWeight="600" fill="#3a4256" fontFamily="Inter">{b.l}</text>
            <text x="40" y="32" textAnchor="middle" fontSize="8" fill="#6a7283" fontFamily="ui-monospace,monospace">{b.s}</text>
            {i < 4 && <path d={`M 84 20 L 92 20`} stroke="#9aa3b2"/>}
          </g>
        ))}
        {/* strikethrough across all */}
        <line x1="-4" y1="20" x2="464" y2="20" stroke="#FF6B7E" strokeWidth="1.5"/>
        <text x="478" y="24" fontSize="11" fill="#FF6B7E" fontFamily="ui-monospace,monospace">~hrs</text>
      </g>

      <text x="20" y="120" fontSize="9" fill="#6a7283" fontFamily="ui-monospace,monospace">5 components · own monitoring · own on-call</text>

      {/* Divider */}
      <line x1="20" y1="180" x2="540" y2="180" stroke="rgba(0,0,0,0.10)" strokeDasharray="3 3"/>

      {/* Bottom: Doris 4.1 native CDC */}
      <text x="20" y="218" fontSize="11" fill="var(--velo-blue)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">B — DORIS 4.1 NATIVE CDC</text>

      <g transform="translate(20, 246)">
        <rect width="100" height="64" rx="8" fill="#eaf4ff" stroke="var(--velo-blue)" strokeWidth="1.4"/>
        <text x="50" y="28" textAnchor="middle" fontSize="13" fontWeight="600" fill="#0a60b5" fontFamily="Inter">PostgreSQL</text>
        <text x="50" y="46" textAnchor="middle" fontSize="9" fill="#4a5872" fontFamily="ui-monospace,monospace">WAL stream</text>

        <path d="M 100 278 L 144 278" stroke="var(--velo-blue)" strokeWidth="1.5"/>
        <path d="M 140 274 L 144 278 L 140 282" stroke="var(--velo-blue)" strokeWidth="1.5" fill="none"/>

        <rect x="148" y="246" width="244" height="64" rx="8" fill="rgba(11,162,255,0.10)" stroke="var(--velo-blue)" strokeWidth="1.5"/>
        <text x="270" y="270" textAnchor="middle" fontSize="10" fill="var(--velo-blue)" fontFamily="ui-monospace,monospace" letterSpacing="0.12em">A SINGLE SQL STATEMENT</text>
        <text x="270" y="290" textAnchor="middle" fontSize="11" fontWeight="600" fill="#0a60b5" fontFamily="ui-monospace,monospace">CREATE JOB ON STREAMING</text>
        <text x="270" y="304" textAnchor="middle" fontSize="11" fontWeight="600" fill="#0a60b5" fontFamily="ui-monospace,monospace">FROM POSTGRES</text>

        <path d="M 396 278 L 440 278" stroke="var(--velo-blue)" strokeWidth="1.5"/>
        <path d="M 436 274 L 440 278 L 436 282" stroke="var(--velo-blue)" strokeWidth="1.5" fill="none"/>

        <rect x="444" y="246" width="86" height="64" rx="8" fill="#eaf4ff" stroke="var(--velo-blue)" strokeWidth="1.4"/>
        <text x="487" y="270" textAnchor="middle" fontSize="13" fontWeight="600" fill="#0a60b5" fontFamily="Inter">VeloDB</text>
        <text x="487" y="288" textAnchor="middle" fontSize="9" fill="#4a5872" fontFamily="ui-monospace,monospace">queryable</text>
        <text x="487" y="300" textAnchor="middle" fontSize="9" fill="#4a5872" fontFamily="ui-monospace,monospace">in ~1s</text>
      </g>

      <g transform="translate(20, 350)">
        <text x="0" y="0" fontSize="10" fill="var(--velo-blue)" fontWeight="600" fontFamily="ui-monospace,monospace">~1 second</text>
        <text x="80" y="0" fontSize="10" fill="#4a5872" fontFamily="ui-monospace,monospace">freshness · zero middleware · schema changes auto-propagate</text>
      </g>
    </svg>
  );
}

function PGDiagramJoins() {
  return (
    <svg viewBox="0 0 560 460" fill="none" preserveAspectRatio="xMidYMid meet" className="pg-diagram">
      <text x="20" y="32" fontSize="11" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">NORMALIZED SCHEMA · NO DENORMALIZATION</text>

      {/* Three tables with join relationships */}
      <g transform="translate(20, 60)">
        <rect width="110" height="80" rx="6" fill="rgba(255,255,255,0.04)" stroke="rgba(255,255,255,0.20)"/>
        <text x="10" y="18" fontSize="11" fontWeight="600" fill="#fff" fontFamily="Inter">orders</text>
        <line x1="10" y1="24" x2="100" y2="24" stroke="rgba(255,255,255,0.15)"/>
        <text x="10" y="38" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">order_id</text>
        <text x="10" y="52" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">customer_id</text>
        <text x="10" y="66" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">product_id</text>
      </g>
      <g transform="translate(20, 160)">
        <rect width="110" height="64" rx="6" fill="rgba(255,255,255,0.04)" stroke="rgba(255,255,255,0.20)"/>
        <text x="10" y="18" fontSize="11" fontWeight="600" fill="#fff" fontFamily="Inter">customers</text>
        <line x1="10" y1="24" x2="100" y2="24" stroke="rgba(255,255,255,0.15)"/>
        <text x="10" y="38" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">customer_id</text>
        <text x="10" y="52" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">segment</text>
      </g>
      <g transform="translate(20, 244)">
        <rect width="110" height="64" rx="6" fill="rgba(255,255,255,0.04)" stroke="rgba(255,255,255,0.20)"/>
        <text x="10" y="18" fontSize="11" fontWeight="600" fill="#fff" fontFamily="Inter">products</text>
        <line x1="10" y1="24" x2="100" y2="24" stroke="rgba(255,255,255,0.15)"/>
        <text x="10" y="38" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">product_id</text>
        <text x="10" y="52" fontSize="9" fill="rgba(255,255,255,0.65)" fontFamily="ui-monospace,monospace">category</text>
      </g>

      {/* join lines */}
      <path d="M 130 130 Q 170 145 130 192" stroke="var(--velo-cyan)" strokeWidth="1" strokeDasharray="3 3" fill="none"/>
      <path d="M 130 130 Q 170 220 130 276" stroke="var(--velo-cyan)" strokeWidth="1" strokeDasharray="3 3" fill="none"/>

      {/* MPP engine */}
      <g transform="translate(220, 100)">
        <rect width="320" height="160" rx="10" fill="rgba(11,162,255,0.08)" stroke="rgba(11,162,255,0.50)"/>
        <text x="160" y="24" textAnchor="middle" fontSize="11" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">VELODB MPP ENGINE</text>

        {/* compute nodes */}
        <g transform="translate(20, 50)">
          {Array.from({ length: 6 }, (_, i) => (
            <g key={i} transform={`translate(${i * 48}, 0)`}>
              <rect width="40" height="50" rx="4" fill="rgba(255,255,255,0.04)" stroke="rgba(26,236,255,0.40)"/>
              <text x="20" y="20" textAnchor="middle" fontSize="9" fill="rgba(255,255,255,0.80)" fontFamily="ui-monospace,monospace">be-{i+1}</text>
              <line x1="6" y1="28" x2="34" y2="28" stroke="rgba(255,255,255,0.10)"/>
              <text x="20" y="40" textAnchor="middle" fontSize="8" fill="rgba(255,255,255,0.55)" fontFamily="ui-monospace,monospace">scan</text>
            </g>
          ))}
        </g>

        {/* join strategies */}
        <g transform="translate(20, 120)">
          {[
            { l: "Broadcast" },
            { l: "Shuffle" },
            { l: "Bucket Shuffle" },
            { l: "Colocate" },
          ].map((s, i) => (
            <g key={s.l} transform={`translate(${i * 72}, 0)`}>
              <rect width="64" height="22" rx="11" fill="rgba(26,236,255,0.10)" stroke="rgba(26,236,255,0.35)"/>
              <text x="32" y="15" textAnchor="middle" fontSize="9" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace">{s.l}</text>
            </g>
          ))}
        </g>
      </g>

      {/* Merge-on-Write strip */}
      <g transform="translate(220, 290)">
        <rect width="320" height="56" rx="8" fill="rgba(255,255,255,0.04)" stroke="rgba(255,255,255,0.15)"/>
        <text x="20" y="22" fontSize="10" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">MERGE-ON-WRITE</text>
        <text x="20" y="40" fontSize="10" fill="rgba(255,255,255,0.78)" fontFamily="Inter">CDC streams in, latest version resolved at write time. 5–10x faster reads.</text>
      </g>

      {/* sub-second gauge */}
      <g transform="translate(220, 376)">
        <rect width="320" height="44" rx="8" fill="rgba(11,162,255,0.10)" stroke="var(--velo-cyan)" strokeWidth="1.5"/>
        <text x="160" y="20" textAnchor="middle" fontSize="11" fill="var(--velo-cyan)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">QUERY RESPONSE</text>
        <text x="160" y="36" textAnchor="middle" fontSize="14" fontWeight="700" fill="#fff" fontFamily="Inter" letterSpacing="-0.01em">sub-second multi-table joins at scale</text>
      </g>
    </svg>
  );
}

function PGDiagramPgvector() {
  return (
    <svg viewBox="0 0 560 460" fill="none" preserveAspectRatio="xMidYMid meet" className="pg-diagram light">
      {/* Left panel: pgvector contention */}
      <g transform="translate(20, 30)">
        <text x="0" y="0" fontSize="11" fill="#FF6B7E" fontFamily="ui-monospace,monospace" letterSpacing="0.12em">WITH PGVECTOR</text>

        <rect x="0" y="14" width="240" height="200" rx="10" fill="#fdf5f6" stroke="rgba(255,80,100,0.40)" strokeWidth="1.2"/>

        {/* Postgres cylinder with stacked workloads */}
        <g transform="translate(40, 38)">
          <ellipse cx="80" cy="10" rx="80" ry="8" fill="#fff" stroke="#FF6B7E"/>
          <path d="M 0 10 v 150 a 80 8 0 0 0 160 0 v -150" fill="#fff" stroke="#FF6B7E"/>
          {/* workload bars */}
          {[
            { y: 30, l: "Transactions", c: "#25D366" },
            { y: 64, l: "Analytics",    c: "#FFAA00" },
            { y: 98, l: "Vector Search",c: "#FF6B7E" },
          ].map((b) => (
            <g key={b.l} transform={`translate(20, ${b.y})`}>
              <rect width="120" height="22" rx="4" fill={b.c} opacity="0.18"/>
              <rect width="6" height="22" rx="3" fill={b.c}/>
              <text x="18" y="15" fontSize="10" fontWeight="600" fill="#3a4256" fontFamily="Inter">{b.l}</text>
            </g>
          ))}
        </g>

        <g transform="translate(36, 184)">
          <circle cx="6" cy="6" r="5" fill="none" stroke="#FF6B7E" strokeWidth="1.5"/>
          <path d="M 3 6 L 9 6 M 6 3 L 6 9" stroke="#FF6B7E" strokeWidth="1.5"/>
          <text x="18" y="10" fontSize="9" fill="#a44550" fontFamily="ui-monospace,monospace">Resource contention on one instance</text>
        </g>
      </g>

      {/* Right panel: VeloDB clean split */}
      <g transform="translate(280, 30)">
        <text x="0" y="0" fontSize="11" fill="var(--velo-blue)" fontFamily="ui-monospace,monospace" letterSpacing="0.12em">WITH VELODB</text>
        <rect x="0" y="14" width="260" height="200" rx="10" fill="#eaf4ff" stroke="var(--velo-blue)" strokeWidth="1.2"/>

        {/* Postgres: just txn */}
        <g transform="translate(14, 32)">
          <ellipse cx="40" cy="10" rx="40" ry="6" fill="#fff" stroke="var(--velo-blue)"/>
          <path d="M 0 10 v 70 a 40 6 0 0 0 80 0 v -70" fill="#fff" stroke="var(--velo-blue)"/>
          <text x="40" y="50" textAnchor="middle" fontSize="10" fontWeight="600" fill="#0a60b5" fontFamily="Inter">Postgres</text>
          <rect x="10" y="62" width="60" height="14" rx="3" fill="rgba(37,211,102,0.20)"/>
          <text x="40" y="73" textAnchor="middle" fontSize="8" fontWeight="600" fill="#1c8a47" fontFamily="Inter">Transactions</text>
        </g>

        {/* CDC arrow */}
        <path d="M 96 80 L 132 80" stroke="var(--velo-blue)" strokeWidth="1.5"/>
        <path d="M 128 76 L 132 80 L 128 84" stroke="var(--velo-blue)" strokeWidth="1.5" fill="none"/>
        <text x="114" y="74" textAnchor="middle" fontSize="8" fill="var(--velo-blue)" fontFamily="ui-monospace,monospace">CDC</text>

        {/* VeloDB */}
        <g transform="translate(132, 28)">
          <ellipse cx="60" cy="10" rx="60" ry="7" fill="#fff" stroke="var(--velo-blue)"/>
          <path d="M 0 10 v 90 a 60 7 0 0 0 120 0 v -90" fill="#fff" stroke="var(--velo-blue)"/>
          <text x="60" y="34" textAnchor="middle" fontSize="10" fontWeight="600" fill="#0a60b5" fontFamily="Inter">VeloDB</text>
          {["Analytics", "Vector Search", "Full-Text"].map((l, i) => (
            <g key={l} transform={`translate(8, ${44 + i * 18})`}>
              <rect width="104" height="14" rx="3" fill="rgba(11,162,255,0.18)"/>
              <text x="52" y="11" textAnchor="middle" fontSize="8" fontWeight="600" fill="#0a60b5" fontFamily="Inter">{l}</text>
            </g>
          ))}
        </g>
      </g>

      {/* Progressive filter funnel */}
      <g transform="translate(280, 254)">
        <rect width="260" height="180" rx="10" fill="#eaf4ff" stroke="var(--velo-blue)" strokeWidth="1.2"/>
        <text x="130" y="22" textAnchor="middle" fontSize="10" fill="var(--velo-blue)" fontFamily="ui-monospace,monospace" letterSpacing="0.14em">PROGRESSIVE FILTERING</text>

        {/* funnel stages */}
        {[
          { y: 38, w: 220, l: "SQL filters", c: "candidate set" },
          { y: 78, w: 160, l: "BM25 keywords", c: "ranked by relevance" },
          { y: 118, w: 100, l: "Vector similarity", c: "small pre-filtered subset" },
        ].map((s, i) => (
          <g key={s.l} transform={`translate(${130 - s.w/2}, ${s.y})`}>
            <rect width={s.w} height="30" rx="4" fill="rgba(11,162,255,0.16)" stroke="var(--velo-blue)"/>
            <text x={s.w / 2} y="14" textAnchor="middle" fontSize="10" fontWeight="600" fill="#0a60b5" fontFamily="Inter">{s.l}</text>
            <text x={s.w / 2} y="25" textAnchor="middle" fontSize="8" fill="#4a5872" fontFamily="ui-monospace,monospace">{s.c}</text>
          </g>
        ))}
        <text x="130" y="162" textAnchor="middle" fontSize="9" fontStyle="italic" fill="#4a5872" fontFamily="ui-monospace,monospace">expensive ops run on a small set</text>
      </g>
    </svg>
  );
}

/* ============================ Value Prop Sections ============================ */
function PGSection({ id, label, light, reverse, headline, paragraphs, cta, outcome, diagram, microStat }) {
  return (
    <section className={`pg-section pg-vp-section ${light ? "light" : "dark"} ${reverse ? "reverse" : ""}`} data-screen-label={label}>
      <div className="wrap">
        <div className="pg-2col">
          <div className="pg-2col-visual">
            <div className="pg-vp-visual-wrap">
              {diagram}
            </div>
            {microStat && (
              <div className={`pg-vp-microstat ${light ? "light" : ""}`}>
                {microStat}
              </div>
            )}
          </div>
          <div className="pg-2col-text">
            <PGContentColumn
              headline={headline}
              paragraphs={paragraphs}
              cta={cta}
              outcome={outcome}
              light={light}
            />
          </div>
        </div>
      </div>
    </section>
  );
}

function PGSections() {
  return (
    <React.Fragment>
      {/* Section 1 — Concurrency (dark, diagram left) */}
      <PGSection
        label="03 Concurrency"
        light={false}
        reverse={false}
        diagram={<PGDiagramConcurrency />}
        microStat="10,000 QPS at 150ms · 4x CPU reduction"
        headline="Thousands of concurrent users should not slow down your database."
        paragraphs={[
          "Postgres handles transactional workloads reliably. But analytical queries compete for the same CPU, memory, and I/O. When concurrent users grow from a handful of analysts to thousands of dashboard sessions, portal users, and API consumers, query latency spikes and transactional performance degrades. Read replicas are still row-based and single-node. They defer the problem without solving it.",
          "VeloDB is a dedicated analytical engine designed for high concurrency from the ground up. Short-Circuit Plan bypasses the full query planner for point lookups and reduces CPU usage by 4x. Hybrid Row and Column Storage eliminates random I/O on wide tables. Row Cache and Prepared Statements keep the hottest query paths in memory. Postgres continues handling transactions while VeloDB serves the analytical read load at any concurrency level.",
        ]}
        cta="Learn how JD.com runs real-time analytics at 10,000 concurrent queries per second"
        outcome={{
          title: "Concurrency Outcome",
          stats: [
            { n: "10,000 QPS", l: "Concurrent analytical queries with 150ms average latency, without touching the transactional database" },
            { n: "4x",         l: "CPU reduction on high-frequency lookups via Short-Circuit Plan, keeping latency flat as users scale" },
          ],
        }}
      />

      {/* Section 2 — Freshness (light, diagram right) */}
      <PGSection
        label="04 Freshness"
        light={true}
        reverse={true}
        diagram={<PGDiagramFreshness />}
        headline="Your analytics should reflect what happened seconds ago, not hours ago."
        paragraphs={[
          "Scaling analytics off Postgres typically means building a pipeline with Debezium to capture changes, Kafka to buffer them, and Flink to transform them before loading into an OLAP engine. Each component adds configuration, monitoring, and failure modes. The result is data that is minutes to hours behind the source, and a pipeline that requires its own engineering team.",
          "VeloDB eliminates the middleware layer entirely. Doris 4.1 native CDC connects to PostgreSQL with a single CREATE JOB ON STREAMING FROM POSTGRES statement, runs a full snapshot of existing data, and then captures changes from the write-ahead log continuously. Dashboards, portals, and APIs reflect what happened in Postgres seconds ago. Schema changes propagate automatically through the stream.",
        ]}
        cta="Learn more about native PostgreSQL CDC in Apache Doris 4.1"
        outcome={{
          title: "Real-Time Freshness Outcome",
          stats: [
            { n: "~1 Second",     l: "Data freshness from PostgreSQL write to queryable result in VeloDB" },
            { n: "Zero Middleware", l: "The entire CDC pipeline is one SQL statement with no Debezium, Kafka, or Flink to deploy or monitor" },
          ],
        }}
      />

      {/* Section 3 — Joins (dark, diagram left) */}
      <PGSection
        label="05 Joins"
        light={false}
        reverse={false}
        diagram={<PGDiagramJoins />}
        microStat="5–10x faster reads on updated data · Sub-second joins at scale"
        headline="Complex joins and aggregations at analytical speed, without denormalizing anything."
        paragraphs={[
          "Postgres can handle joins, but not at the speed and concurrency that analytical workloads demand at scale. The typical workaround is denormalization: pre-flatten fact and dimension tables into wide redundant copies optimized for specific read patterns. Storage bloats, pipelines multiply, and every upstream schema change forces a rebuild of the flattened tables.",
          "VeloDB's columnar MPP engine runs multi-table joins, complex aggregations, and high-cardinality group-by queries at sub-second speed on normalized data. The cost-based optimizer automatically selects from Broadcast, Shuffle, Bucket Shuffle, and Colocate join strategies based on table statistics. Merge-on-Write resolves CDC record versions at write time, so queries on frequently updated data run 5 to 10x faster than merge-on-read engines. Your data model stays clean while your analytical queries stay fast.",
        ]}
        cta="Learn how Merge-on-Write accelerates real-time analytics on changing data"
        outcome={{
          title: "Analytical Speed Outcome",
          stats: [
            { n: "5–10x",    l: "Faster reads on frequently updated datasets via Merge-on-Write, with no query-time deduplication overhead" },
            { n: "Sub-second", l: "Multi-table joins across fact and dimension tables using automatic join strategy selection" },
          ],
        }}
      />

      {/* Section 4 — pgvector (light, diagram right) */}
      <PGSection
        label="06 pgvector"
        light={true}
        reverse={true}
        diagram={<PGDiagramPgvector />}
        headline="pgvector adds AI workloads to an already constrained database."
        paragraphs={[
          "pgvector is a useful extension for small-scale similarity search. But it runs on the same Postgres instance that is already under pressure from analytical and transactional workloads. Every vector query competes for the same CPU, memory, and I/O. pgvector is single-node, stores vectors in row format, and lacks a cost-based optimizer for queries that need to combine structured filters with similarity ranking. As the embedding corpus grows, Postgres carries an even heavier load.",
          "VeloDB handles vector similarity alongside columnar analytics and full-text search in a dedicated engine that never touches your Postgres transactional workload. Progressive filtering applies SQL constraints first, BM25 keyword matching second, and vector search last on a small pre-filtered subset. Expensive vector operations run on a fraction of the data, delivering higher relevance at lower compute cost. If you need AI-powered retrieval alongside real-time analytics, VeloDB handles both without overloading Postgres.",
        ]}
        cta="Learn about progressive filtering and hybrid search in Apache Doris 4.0"
        outcome={{
          title: "pgvector vs VeloDB Outcome",
          stats: [
            { n: "58% → 94%", l: "Relevance improvement when progressive filtering narrows candidates before vector search" },
            { n: "20x",       l: "Memory reduction with IVPQ compression, enabling billion-scale vector search on a fraction of the hardware" },
          ],
        }}
      />
    </React.Fragment>
  );
}

/* ============================ Contact (dark, centered) ============================ */
function PGContactCTA() {
  return (
    <section style={{ padding: "80px 0 120px" }} data-screen-label="07 Contact">
      <div className="wrap">
        <div className="final-cta">
          <h2>Need help scaling your Postgres analytics?</h2>
          <p>Submit your product and service requirements and a VeloDB engineer will respond within one business day.</p>
          <div className="ctas">
            <button className="btn btn-primary btn-lg">Contact us</button>
            <button className="btn btn-ghost btn-lg">Start Free Cloud Trial</button>
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { PGHero, PGRelease, PGSections, PGContactCTA });
