// Architecture page — NVIDIA GPU Compute Network Reference Architecture
// Card-based technical articles. Clicking a card opens a slide-in canvas
// from the right; clicking the backdrop (or pressing Esc) closes it.

const { useState, useEffect } = React;

/* ---------- Scale profile data (GB200 NVL72, 4-rail) ---------- */
const GB200_PROFILES = [
{ gpus: 144, servers: 2, nics: 144, leaf: 1, tor: 2, gpuRack: 2, swRack: 1, power: 249.7 },
{ gpus: 216, servers: 3, nics: 216, leaf: 2, tor: 4, gpuRack: 3, swRack: 1, power: 380.0 },
{ gpus: 432, servers: 6, nics: 432, leaf: 4, tor: 8, gpuRack: 6, swRack: 2, power: 759.0 },
{ gpus: 864, servers: 12, nics: 864, leaf: 8, tor: 16, gpuRack: 12, swRack: 3, power: 1518.0 },
{ gpus: 1728, servers: 24, nics: 1728, leaf: 16, tor: 32, gpuRack: 24, swRack: 6, power: 3036.0 },
{ gpus: 3456, servers: 48, nics: 3456, leaf: 27, tor: 64, gpuRack: 48, swRack: 12, power: 6055.0 },
{ gpus: 6912, servers: 96, nics: 6912, leaf: 54, tor: 128, gpuRack: 96, swRack: 24, power: 12111.0 }];


/* ---------- Scale profile data (GB300 NVL72, TH5 800G, Spine/Leaf) ---------- */
const GB300_PROFILES = [
{ gpus: 144, servers: 2, nics: 144, spine: 3, leaf: 6, oOsfp: 144, oMpo: 288, oOsfp2: 144, uOsfp: 144, uMpo: 288, uOsfp2: 144 },
{ gpus: 216, servers: 3, nics: 216, spine: 3, leaf: 6, oOsfp: 216, oMpo: 432, oOsfp2: 216, uOsfp: 216, uMpo: 432, uOsfp2: 216 },
{ gpus: 432, servers: 6, nics: 432, spine: 6, leaf: 12, oOsfp: 432, oMpo: 864, oOsfp2: 432, uOsfp: 432, uMpo: 864, uOsfp2: 432 },
{ gpus: 864, servers: 12, nics: 864, spine: 12, leaf: 24, oOsfp: 864, oMpo: 1728, oOsfp2: 864, uOsfp: 864, uMpo: 1728, uOsfp2: 864 },
{ gpus: 1728, servers: 24, nics: 1728, spine: 24, leaf: 48, oOsfp: 1728, oMpo: 3456, oOsfp2: 1728, uOsfp: 1728, uMpo: 3456, uOsfp2: 1728 }];


/* ---------- Scale profile data (H200/B200 8-rail) ---------- */
const SCALE_PROFILES = [
{ gpus: 128, servers: 16, nics: 128, leaf: 0, tor: 1, gpuRack: 8, swRack: 1, power: 163.2 },
{ gpus: 256, servers: 32, nics: 256, leaf: 2, tor: 4, gpuRack: 16, swRack: 1, power: 339.5 },
{ gpus: 512, servers: 64, nics: 512, leaf: 4, tor: 8, gpuRack: 32, swRack: 2, power: 680.2 },
{ gpus: 1024, servers: 128, nics: 1024, leaf: 8, tor: 16, gpuRack: 64, swRack: 3, power: 1358.4 },
{ gpus: 2048, servers: 256, nics: 2048, leaf: 16, tor: 32, gpuRack: 128, swRack: 6, power: 2716.8 },
{ gpus: 4096, servers: 512, nics: 4096, leaf: 32, tor: 64, gpuRack: 256, swRack: 12, power: 5433.6 },
{ gpus: 8192, servers: 1024, nics: 8192, leaf: 64, tor: 128, gpuRack: 512, swRack: 24, power: 10867.2 }];


const fmt = (n) => n.toLocaleString('en-US');

/* ---------- Article 1: H200/B200 8-Rail Architecture body ---------- */
const ArticleH200B200 = () =>
<>
    {/* Executive Summary */}
    <section className="art-section">
      <h3 className="art-h3">Executive Summary</h3>
      <p className="art-p">
        This reference architecture defines an <b>8-rail, non-blocking RoCEv2 compute
        fabric</b> for NVIDIA <b>H200</b> and <b>B200</b> GPU servers, using
        <b> 400G/OSFP</b> end-to-end with a two-tier Leaf/Spine topology of <b>128×400G</b>
        platform switches. The design is rail-aligned: each of a server's 8 GPU
        NICs lands on a dedicated TOR ("rail") so that <b>same-rank collectives
        traverse a single switch hop</b>, eliminating cross-rail oversubscription for
        NCCL ring/tree primitives at intra-pod scale.
      </p>
      <p className="art-p">
        The architecture scales linearly from a <b>128-GPU pod</b> (single TOR per
        rail) to a <b>8,192-GPU AI factory</b> (16 pods × 8 rails) under a single
        addressing and routing domain, with deterministic optics and power
        budgets at every step. Total fabric power tracks at <b>~1.33 kW per GPU
        node-equivalent</b> across the scale band.
      </p>
    </section>

    {/* Topology */}
    <section className="art-section">
      <h3 className="art-h3">Fabric Topology</h3>
      <p className="art-p">
        Each <b>Server Group</b> consists of <b>64 GPU servers</b> (512 GPUs) front-ended
        by <b>8 TOR switches</b>, one per rail. NIC<sub></sub> on every server in the
        group connects only to TOR<sub>i</sub> — the rail-aligned plane. The 8 TORs of
        a group fan up north to the <b>Leaf layer</b> in a full mesh, with up to
        <b> 16 groups (MAX)</b> per pod under the 64-leaf footprint shown below.
      </p>
      <div className="art-figure">
        <iframe
        src="assets/network-topology.html"
        title="H200/B200 8-Rail Network Topology"
        className="art-iframe"
        loading="lazy" />
      </div>
      <div className="art-callouts">
        <div className="art-callout">
          <div className="art-callout__k">Per-Leaf radix</div>
          <div className="art-callout__v">128 × 400G</div>
          <div className="art-callout__s">128 downlinks to TOR layer</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Per-TOR radix</div>
          <div className="art-callout__v">64↑ / 64↓ × 400G</div>
          <div className="art-callout__s">1:1 non-blocking, 64 servers / TOR</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Per-Server</div>
          <div className="art-callout__v">8 × 400G</div>
          <div className="art-callout__s">1 NIC per GPU, rail-aligned</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Bisection BW (pod)</div>
          <div className="art-callout__v">3.2 Tb/s / server</div>
          <div className="art-callout__s">Full bisection within rail plane</div>
        </div>
      </div>
    </section>

    {/* Design Principles */}
    <section className="art-section">
      <h3 className="art-h3">Design Principles</h3>
      <ul className="art-list">
        <li><b>Rail alignment.</b> All 8 GPU NICs on a server map 1:1 to 8 dedicated TORs. Same-rank NCCL collectives (AllReduce ring, tree, recursive halving-doubling) stay on a single rail plane and complete in one ToR hop at intra-group scale.</li>
        <li><b>Non-blocking 1:1 oversubscription.</b> Each TOR exposes 64×400G south (servers) and 64×400G north (Leaf) — no oversubscription within the compute fabric.</li>
        <li><b>Uniform 400G fabric.</b> 400G-OSFP / 400G-QSFP112 end-to-end, no speed transitions, enabling RoCEv2 PFC / ECN tuning to be applied uniformly.</li>
        <li><b>Pod-and-Group scaling unit.</b> The atomic scale unit is the <b>Group</b> (64 servers / 512 GPUs / 8 TORs). Pods scale by adding Groups up to 16; AI factories scale by replicating pods.</li>
        <li><b>Cabling determinism.</b> Optics and jumper counts are exact integer multiples of (servers × 8) and (TOR × leaf radix). No partial bundles, no stranded ports.</li>
      </ul>
    </section>

    {/* Scaling Profiles Table */}
    <section className="art-section">
      <h3 className="art-h3">Scaling Profiles · 128 → 8,192 GPUs</h3>
      <p className="art-p">
        The table below codifies the deterministic BOM for every scale tier. All
        rows derive from three invariants: <b>8 GPUs/server</b>, <b>8 NICs/server</b>
        (1×400G each), and <b>128-port 400G platform switches</b> at both TOR and
        Leaf. Optics quantities are split by segment (NIC↔TOR vs TOR↔Leaf) and by
        media type.
      </p>

      <div className="scale-table">
        <div className="scale-table__scroll">
          <table>
            <thead>
              <tr>
                <th rowSpan="2" className="st-type">Type</th>
                <th rowSpan="2" className="st-name">Component</th>
                <th colSpan={SCALE_PROFILES.length} className="st-group">GPU scale</th>
              </tr>
              <tr>
                {SCALE_PROFILES.map((p) =>
              <th key={p.gpus} className="st-col">
                    <div className="st-col__n">{fmt(p.gpus)}</div>
                    <div className="st-col__u">GPUs</div>
                  </th>
              )}
              </tr>
            </thead>
            <tbody>
              <tr className="st-band">
                <td className="st-type">Compute</td>
                <td className="st-name">GPU chips <span className="st-name__sub">(8 per server)</span></td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.gpus)}</td>)}
              </tr>
              <tr>
                <td className="st-type"></td>
                <td className="st-name">AI servers <span className="st-name__sub">(8×H200 / 8×B200)</span></td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.servers)}</td>)}
              </tr>
              <tr>
                <td className="st-type"></td>
                <td className="st-name">Network cards <span className="st-name__sub">(8 × 1×400G per server)</span></td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="2">Switching<br /><span className="st-type__sub">128 × 400G</span></td>
                <td className="st-name">Leaf</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{p.leaf === 0 ? '—' : fmt(p.leaf)}</td>)}
              </tr>
              <tr>
                <td className="st-name">TOR</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.tor)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="2">Cabinet</td>
                <td className="st-name">GPU server rack <span className="st-name__sub">(42U)</span></td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.gpuRack)}</td>)}
              </tr>
              <tr>
                <td className="st-name">Switch rack <span className="st-name__sub">(42U)</span></td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.swRack)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="6">Optics &<br />jumpers</td>
                <td className="st-name"><span className="st-seg">NIC ↔ TOR</span> 400G-OSFP-SR4</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg">NIC ↔ TOR</span> MPO-MPO-OM4</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg">NIC ↔ TOR</span> 400G-QSFP112-SR4</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">TOR ↔ Leaf</span> 400G-QSFP112-SR4</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{p.leaf === 0 ? '—' : fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">TOR ↔ Leaf</span> MPO-MPO-OM4</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{p.leaf === 0 ? '—' : fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">TOR ↔ Leaf</span> 400G-QSFP112-SR4</td>
                {SCALE_PROFILES.map((p) => <td key={p.gpus} className="st-num">{p.leaf === 0 ? '—' : fmt(p.nics)}</td>)}
              </tr>

              <tr className="st-band st-band--total">
                <td className="st-type">Power</td>
                <td className="st-name">Total (server + switch) <span className="st-name__sub">kW</span></td>
                {SCALE_PROFILES.map((p) =>
              <td key={p.gpus} className="st-num st-num--accent">
                    {p.power.toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 })}
                  </td>
              )}
              </tr>
            </tbody>
          </table>
        </div>
        <div className="scale-table__legend">
          <span className="st-legend__item"><span className="st-dot st-dot--rail"></span>NIC ↔ TOR · rail-aligned, intra-group</span>
          <span className="st-legend__item"><span className="st-dot st-dot--upl"></span>TOR ↔ Leaf · north uplinks, inter-group</span>
          <span className="st-legend__item st-legend__note">Optics counts assume single-mode-free SR4 plant; substitute LR4 / DR4 per facility reach.</span>
        </div>
      </div>
    </section>

    {/* Technical Notes by Layer */}
    <section className="art-section">
      <h3 className="art-h3">Layer-by-Layer Technical Notes</h3>

      <div className="art-tech-grid">
        <div className="art-tech">
          <div className="art-tech__k">Compute node</div>
          <div className="art-tech__body">
            <p>8 × H200 or B200 SXM GPUs per chassis with <b>NVLink/NVSwitch</b> for intra-node collectives. Each GPU is paired 1:1 with a <b>ConnectX-7 / BlueField-3 400G</b> NIC, BDF-affined to the GPU's NUMA / PCIe root complex. GPUDirect RDMA is mandatory; PCIe Gen5 ×16 per NIC.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">TOR / Rail switch</div>
          <div className="art-tech__body">
            <p><b>128-port 400G</b> platform (e.g. Spectrum-4 SN5600 class). 64 ports south to 64 servers, 64 ports north to Leaf. <b>RoCEv2</b> with <b>PFC + ECN</b>, DCQCN tuned, lossless on the GPU traffic class.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Leaf / Spine switch</div>
          <div className="art-tech__body">
            <p>Same 128 × 400G platform used as <b>Leaf</b>. Within a 16-group pod, 64 Leaves × 128 ports = 8,192 downlinks, exactly matching 128 TOR × 64 uplinks. No oversubscription, no port stranding.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Optics &amp; cabling</div>
          <div className="art-tech__body">
            <p><b>400G-OSFP-SR4</b> on the NIC side, <b>400G-QSFP112-SR4</b> on the switch side, joined by <b>MPO-12 OM4</b> trunks. Reach: 100 m on OM4. Substitute <b>DR4</b> / <b>LR4</b> for cross-hall runs.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Power &amp; thermal</div>
          <div className="art-tech__body">
            <p>Per-rack envelope sized for <b>~10.2 kW/server</b> at sustained load. 8 servers per 42U GPU rack drives <b>≥ 80–100 kW</b> rack density — liquid-assist or rear-door heat exchangers assumed at and above the 512-GPU tier.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Out-of-band</div>
          <div className="art-tech__body">
            <p>Separate <b>1G/10G management plane</b> (NMIX / BCM / NetQ) on dedicated OOB switches in the switch rack — never folded into the compute fabric. BMC, switch console, and PDU telemetry isolated from RoCE traffic.</p>
          </div>
        </div>
      </div>
    </section>
  </>;


/* ---------- Article 2: GB200 NVL72 4-Rail Architecture body ---------- */
const ArticleGB200NVL72 = () =>
<>
    {/* Executive Summary */}
    <section className="art-section">
      <h3 className="art-h3">Executive Summary</h3>
      <p className="art-p">
        This reference architecture defines a <b>4-rail, non-blocking RoCEv2 compute
        fabric</b> for the NVIDIA <b>GB200 NVL72</b> rack-scale platform. Each NVL72
        is treated as a single compute unit — <b>72 Blackwell GPUs</b> interconnected
        via a 5th-gen <b>NVLink Switch fabric</b> at <b>1.8 TB/s per GPU</b> — and front-ended
        on the scale-out fabric by <b>72 × 400G RoCE NICs</b> (one NIC per GPU) arranged in
        4 rail planes of 18 NICs each.
      </p>
      <p className="art-p">
        The design scales from a <b>144-GPU pair</b> (2 NVL72 racks, one rail-spine pair)
        to a <b>6,912-GPU AI factory</b> (96 NVL72 racks). At full scale, the compute fabric
        comprises <b>128 TOR</b> + <b>54 Leaf</b> switches with <b>~12.1 MW</b> of compute
        load behind a single addressing and routing domain. Per-rack density lands at
        <b> ~126 kW</b> — liquid cooling is non-optional from the first rack.
      </p>
    </section>

    {/* Why NVL72 changes the network */}
    <section className="art-section">
      <h3 className="art-h3">Why NVL72 Changes the Network Design</h3>
      <p className="art-p">
        With NVL72, the <b>scale-up domain expands from 8 GPUs (HGX) to 72 GPUs (rack)</b>.
        That shifts the boundary between NVLink (intra-rack, all-to-all at 1.8 TB/s) and
        RoCE (inter-rack, scale-out). Three consequences for fabric design:
      </p>
      <ul className="art-list">
        <li><b>Fewer rail planes, denser per-rail capacity.</b> 4 rails × 18 NICs/rail per rack — vs HGX's 8 rails × 1 NIC/rail. Each rail plane carries 7.2 Tb/s out of every NVL72.</li>
        <li><b>Rack <i>is</i> the server.</b> The atomic compute and cabling unit is the NVL72 rack itself, not a 4U/8U chassis. Every BOM line — power, cooling, optics, structured cabling — is sized against rack count, not server count.</li>
        <li><b>Collective patterns shift.</b> Most tensor / pipeline parallelism stays inside the NVLink domain. The RoCE fabric is dominated by <b>data-parallel AllReduce</b> across racks and <b>expert / MoE routing</b> — bursty, but rail-resident at intra-pod scale.</li>
      </ul>
    </section>

    {/* Topology */}
    <section className="art-section">
      <h3 className="art-h3">Fabric Topology</h3>
      <p className="art-p">
        Each NVL72 rack exposes 72 NICs split across <b>4 rail planes</b> (NICs 1–18 →
        Rail 1, 19–36 → Rail 2, …). Within a pod, each rail plane is served by its
        own set of TORs that aggregate up to the Leaf layer in a full mesh. Cross-rail
        traffic is the exception — addressed by the Leaf layer when it occurs.
      </p>
      <div className="art-figure">
        <iframe
        src="assets/network-topology-rack.html"
        title="GB200 NVL72 4-Rail Network Topology"
        className="art-iframe art-iframe--tall"
        loading="lazy" />
      </div>
      <div className="art-callouts">
        <div className="art-callout">
          <div className="art-callout__k">Per-rack GPUs</div>
          <div className="art-callout__v">72 × Blackwell</div>
          <div className="art-callout__s">NVL72 scale-up domain (NVLink 5)</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Per-rack NICs</div>
          <div className="art-callout__v">72 × 400G</div>
          <div className="art-callout__s">1 NIC per GPU, 4 rails × 18</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Per-rack RoCE BW</div>
          <div className="art-callout__v">28.8 Tb/s</div>
          <div className="art-callout__s">Scale-out, east-west</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Per-rack power</div>
          <div className="art-callout__v">~126 kW</div>
          <div className="art-callout__s">Liquid cooling required</div>
        </div>
      </div>
    </section>

    {/* Design Principles */}
    <section className="art-section">
      <h3 className="art-h3">Design Principles</h3>
      <ul className="art-list">
        <li><b>Rail alignment, rack-scaled.</b> Rail mapping is preserved across the larger 72-NIC payload — 18 NICs per rail per rack, all landing on rail-affined TORs. Single-hop within rail at intra-pod scale.</li>
        <li><b>NVLink owns intra-rack, RoCE owns inter-rack.</b> No design pressure to push intra-NVL72 traffic onto the scale-out fabric. Each domain runs to its strengths.</li>
        <li><b>Non-blocking 400G end-to-end.</b> 1:1 oversubscription on every TOR and Leaf. Speed transitions and breakouts are explicitly avoided in the compute fabric.</li>
        <li><b>Power-aware unit of scale.</b> The scale unit is the NVL72 rack at ~126 kW. Pod planning is gated by <i>power and cooling delivery</i> as much as by switch radix.</li>
        <li><b>Storage and management on dedicated planes.</b> Separate fabrics for storage (DPU-attached) and OOB management (BMC, BCM, NetQ) — never folded into the compute RoCE plane.</li>
      </ul>
    </section>

    {/* Scaling Profiles Table */}
    <section className="art-section">
      <h3 className="art-h3">Scaling Profiles · 144 → 6,912 GPUs</h3>
      <p className="art-p">
        The table codifies the deterministic BOM for every scale tier. All rows derive
        from three invariants: <b>72 GPUs per NVL72</b>, <b>72 × 400G NICs per NVL72</b>,
        and <b>128-port 400G platform switches</b> at both TOR and Leaf. Optics counts
        are reported per segment (NIC↔TOR vs TOR↔Leaf) and per media type.
      </p>

      <div className="scale-table">
        <div className="scale-table__scroll">
          <table>
            <thead>
              <tr>
                <th rowSpan="2" className="st-type">Type</th>
                <th rowSpan="2" className="st-name">Component</th>
                <th colSpan={GB200_PROFILES.length} className="st-group">GPU scale</th>
              </tr>
              <tr>
                {GB200_PROFILES.map((p) =>
              <th key={p.gpus} className="st-col">
                    <div className="st-col__n">{fmt(p.gpus)}</div>
                    <div className="st-col__u">GPUs</div>
                  </th>
              )}
              </tr>
            </thead>
            <tbody>
              <tr className="st-band">
                <td className="st-type">Compute</td>
                <td className="st-name">GPU chips <span className="st-name__sub">(72 per NVL72 rack)</span></td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.gpus)}</td>)}
              </tr>
              <tr>
                <td className="st-type"></td>
                <td className="st-name">AI servers <span className="st-name__sub">(NVL72 sets)</span></td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.servers)}</td>)}
              </tr>
              <tr>
                <td className="st-type"></td>
                <td className="st-name">Network cards <span className="st-name__sub">(72 × 1×400G per NVL72)</span></td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="2">Switching<br /><span className="st-type__sub">128 × 400G</span></td>
                <td className="st-name">Leaf</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.leaf)}</td>)}
              </tr>
              <tr>
                <td className="st-name">TOR</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.tor)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="2">Cabinet</td>
                <td className="st-name">GPU server rack <span className="st-name__sub">(NVL72)</span></td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.gpuRack)}</td>)}
              </tr>
              <tr>
                <td className="st-name">Switch rack <span className="st-name__sub">(42U)</span></td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.swRack)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="6">Optics &<br />jumpers</td>
                <td className="st-name"><span className="st-seg">NIC ↔ TOR</span> 400G-OSFP-SR4</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg">NIC ↔ TOR</span> MPO-MPO-OM4</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg">NIC ↔ TOR</span> 400G-QSFP112-SR4</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">TOR ↔ Leaf</span> 400G-QSFP112-SR4</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">TOR ↔ Leaf</span> MPO-MPO-OM4</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">TOR ↔ Leaf</span> 400G-QSFP112-SR4</td>
                {GB200_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>

              <tr className="st-band st-band--total">
                <td className="st-type">Power</td>
                <td className="st-name">Total (server + switch) <span className="st-name__sub">kW</span></td>
                {GB200_PROFILES.map((p) =>
              <td key={p.gpus} className="st-num st-num--accent">
                    {p.power.toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 })}
                  </td>
              )}
              </tr>
            </tbody>
          </table>
        </div>
        <div className="scale-table__legend">
          <span className="st-legend__item"><span className="st-dot st-dot--rail"></span>NIC ↔ TOR · rail-aligned, intra-pod</span>
          <span className="st-legend__item"><span className="st-dot st-dot--upl"></span>TOR ↔ Leaf · north uplinks, inter-rack</span>
          <span className="st-legend__item st-legend__note">Optics counts assume SR4 plant; substitute DR4 / LR4 for cross-hall reach.</span>
        </div>
      </div>
    </section>

    {/* Technical Notes by Layer */}
    <section className="art-section">
      <h3 className="art-h3">Layer-by-Layer Technical Notes</h3>

      <div className="art-tech-grid">
        <div className="art-tech">
          <div className="art-tech__k">NVL72 rack</div>
          <div className="art-tech__body">
            <p><b>72 Blackwell GPUs</b> (36 GB200 superchips × 2 GPUs) interconnected by 9 <b>NVSwitch</b> trays. Intra-rack NVLink bandwidth is <b>1.8 TB/s per GPU</b>, <b>130 TB/s rack aggregate</b>. Liquid cooling (CDU + manifold) is integrated; air-cooled NVL72 variants are not in scope.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">NIC &amp; rail mapping</div>
          <div className="art-tech__body">
            <p><b>72 × ConnectX-7 / BlueField-3</b> NICs at 400G — one per GPU, PCIe Gen5 ×16. NICs are partitioned into <b>4 rail planes</b> (18 NICs per rail). Each NIC<sub>i</sub> bonds to TOR<sub>rail(i)</sub> on its rail plane. GPUDirect RDMA enabled per-NIC.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">TOR / Rail switch</div>
          <div className="art-tech__body">
            <p><b>128-port 400G</b> platform (Spectrum-4 SN5600 class) operating in <b>rail-pinned</b> mode. 64 ports south to NVL72 racks (rail-aligned), 64 north to Leaf. <b>RoCEv2</b> with PFC + ECN; DCQCN tuned for high-radix bursts typical of MoE routing.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Leaf / Spine switch</div>
          <div className="art-tech__body">
            <p>Same 128 × 400G platform reused at Leaf. Inter-rail traffic (rare under rail-aligned collectives) is resolved one Leaf hop above the rail plane. At <b>54 Leaves × 128 ports</b>, a 6,912-GPU pod fits in a single addressing / routing domain.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Optics &amp; cabling</div>
          <div className="art-tech__body">
            <p><b>400G-OSFP-SR4</b> NIC-side, <b>400G-QSFP112-SR4</b> switch-side, joined by <b>MPO-12 OM4</b> trunks. With 72 NICs per rack, <b>structured cabling is racked into the NVL72 itself</b> — no top-rack jumper farms. Cable bundle counts dominate the deployment plan.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Power, cooling, density</div>
          <div className="art-tech__body">
            <p>NVL72 rack envelope at <b>~126 kW</b>; deployment requires <b>liquid-cooled CDU</b> capacity at the row, redundant <b>415V/3-phase</b> feeds, and structural floor loading review. Adjacent switch racks designed as <b>air-cooled, hot-aisle-contained</b> at 6–10 kW each.</p>
          </div>
        </div>
      </div>
    </section>
  </>;


/* ---------- Article 3: GB300 NVL72 RoCE TH5-800G body ---------- */
const ArticleGB300TH5 = () =>
<>
    {/* Executive Summary */}
    <section className="art-section">
      <h3 className="art-h3">Executive Summary</h3>
      <p className="art-p">
        This reference architecture defines a <b>two-tier Spine–Leaf RoCEv2 fabric</b>
        built on <b>Broadcom Tomahawk 5 (TH5)</b> 64×800G platforms, sized for
        NVIDIA <b>GB300 NVL72</b> rack-scale systems. Every GPU is fronted by its own
        <b> 800G OSFP NIC</b> — doubling per-GPU scale-out bandwidth vs the
        400G (GB200) reference — with optics, switches, and structured cabling
        sized to a single deterministic BOM at every scale tier.
      </p>
      <p className="art-p">
        The design scales from a <b>144-GPU pair</b> (2 NVL72 racks, 3 spines / 6 leaves)
        to a <b>1,728-GPU pod</b> (24 NVL72 racks, 24 spines / 48 leaves) under
        a single non-blocking fabric domain. TH5 switches operate at <b>51.2 Tb/s</b>
        per box, collapsing the rail layer and enabling a flat <b>Spine–Leaf</b>
        topology with full 1:1 oversubscription end-to-end.
      </p>
    </section>

    {/* Why TH5 + GB300 collapses the topology */}
    <section className="art-section">
      <h3 className="art-h3">Why TH5 + GB300 Collapses the Topology</h3>
      <p className="art-p">
        Two technology shifts let this design drop the rail/TOR layer used in 400G
        references and run a clean <b>Spine–Leaf</b> fabric:
      </p>
      <ul className="art-list">
        <li><b>800G per NIC.</b> One 800G OSFP per GPU — vs 1 × 400G in GB200 — doubles per-GPU scale-out bandwidth and reduces NIC count for equivalent throughput.</li>
        <li><b>64×800G TH5 silicon.</b> Each switch delivers 51.2 Tb/s of forwarding at line rate. A single Spine box can backplane 32 Leaves at 1:1; a Leaf can backplane 32 NVL72 NICs south and 32 Spines north without oversubscription.</li>
        <li><b>Flatter, fewer hops.</b> Two switch tiers, two hops maximum across the fabric. Lower P99 latency, simpler ECMP, simpler PFC/ECN domain.</li>
        <li><b>Optics density doubles.</b> 800G-OSFP NIC-side and 800G-OSFP switch-side, joined by <b>2 × MPO-12 OM4</b> per link (one MPO per 400G half). Cable count per link doubles; per-rack optic count tracks GPU count.</li>
      </ul>
    </section>

    {/* Topology */}
    <section className="art-section">
      <h3 className="art-h3">Fabric Topology</h3>
      <p className="art-p">
        Each NVL72 rack exposes <b>72 OSFP NICs</b> at 800G — one per Blackwell GPU.
        NICs land on a set of <b>800G Leaf</b> switches; Leaves fan north to a smaller
        set of <b>800G Spine</b> switches in a full mesh. Within the pod, the fabric is
        <b> 1:1 non-blocking</b> end-to-end.
      </p>
      <div className="art-figure">
        <iframe
        src="assets/network-topology-spine.html"
        title="GB300 NVL72 RoCE TH5-800G Spine–Leaf Topology"
        className="art-iframe art-iframe--tall"
        loading="lazy" />
      </div>
      <div className="art-callouts">
        <div className="art-callout">
          <div className="art-callout__k">Per-NIC speed</div>
          <div className="art-callout__v">800G OSFP</div>
          <div className="art-callout__s">1 NIC per GPU, 72 per NVL72</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Switch silicon</div>
          <div className="art-callout__v">64 × 800G TH5</div>
          <div className="art-callout__s">51.2 Tb/s per switch, 1:1 NB</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Per-rack RoCE BW</div>
          <div className="art-callout__v">57.6 Tb/s</div>
          <div className="art-callout__s">72 × 800G — 2× vs GB200</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Hop count</div>
          <div className="art-callout__v">≤ 2 switch hops</div>
          <div className="art-callout__s">Flat Spine–Leaf, no TOR</div>
        </div>
      </div>
    </section>

    {/* Design Principles */}
    <section className="art-section">
      <h3 className="art-h3">Design Principles</h3>
      <ul className="art-list">
        <li><b>Spine–Leaf, no TOR.</b> With TH5 radix the rail/TOR tier collapses into the Leaf. Fewer ports, fewer optics, fewer cable runs at equivalent throughput.</li>
        <li><b>1:1 non-blocking, end-to-end.</b> South radix = north radix on every Leaf. No oversubscription on the compute plane; storage and management stay on dedicated fabrics.</li>
        <li><b>Uniform 800G fabric.</b> No speed transitions, no breakouts. PFC / ECN / DCQCN parameters tuned once for one link speed.</li>
        <li><b>NVL72 owns intra-rack, RoCE owns inter-rack.</b> NVLink 5 carries the 130 TB/s intra-rack all-to-all. The 800G fabric exists for data-parallel AllReduce and MoE/EP cross-rack routing.</li>
        <li><b>Deterministic BOM at every tier.</b> Optic counts, MPO trunks, switch counts, and rack counts are exact integer multiples of GPU count — no stranded ports, no partial bundles.</li>
      </ul>
    </section>

    {/* Scaling Profiles Table */}
    <section className="art-section">
      <h3 className="art-h3">Scaling Profiles · 144 → 1,728 GPUs</h3>
      <p className="art-p">
        The table codifies the deterministic BOM for every scale tier. All rows derive
        from three invariants: <b>72 GPUs per NVL72</b>, <b>72 × 800G OSFP NICs per
        NVL72</b>, and <b>64-port 800G TH5 platform switches</b> at both Leaf and Spine.
        Per‑link optics are <b>2× MPO-12 OM4 trunks + 2× 800G-OSFP</b> transceivers,
        which is why MPO counts run at 2× the per-link count.
      </p>

      <div className="scale-table">
        <div className="scale-table__scroll">
          <table>
            <thead>
              <tr>
                <th rowSpan="2" className="st-type">Type</th>
                <th rowSpan="2" className="st-name">COMPONENT</th>
                <th colSpan={GB300_PROFILES.length} className="st-group">GPU scale</th>
              </tr>
              <tr>
                {GB300_PROFILES.map((p) =>
              <th key={p.gpus} className="st-col">
                    <div className="st-col__n">{fmt(p.gpus)}</div>
                    <div className="st-col__u">GPUs</div>
                  </th>
              )}
              </tr>
            </thead>
            <tbody>
              <tr className="st-band">
                <td className="st-type">Compute</td>
                <td className="st-name">GPU chips <span className="st-name__sub">(72 per NVL72 rack)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.gpus)}</td>)}
              </tr>
              <tr>
                <td className="st-type"></td>
                <td className="st-name">AI servers <span className="st-name__sub">(NVL72 sets)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.servers)}</td>)}
              </tr>
              <tr>
                <td className="st-type"></td>
                <td className="st-name">RoCE network cards <span className="st-name__sub">(72 × 1×800G per NVL72)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.nics)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="2">Switching<br /><span className="st-type__sub">64 × 800G TH5</span></td>
                <td className="st-name">Spine</td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.spine)}</td>)}
              </tr>
              <tr>
                <td className="st-name">Leaf</td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.leaf)}</td>)}
              </tr>

              <tr className="st-band">
                <td className="st-type" rowSpan="6">Transceivers<br />&amp; cables</td>
                <td className="st-name"><span className="st-seg">NIC ↔ Leaf</span> 800G-OSFP</td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.oOsfp)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg">NIC ↔ Leaf</span> MPO-MPO-OM4 <span className="st-name__sub">(2× per link)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.oMpo)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg">NIC ↔ Leaf</span> 800G-OSFP <span className="st-name__sub">(switch-side)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.oOsfp2)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">Leaf ↔ Spine</span> 800G-OSFP</td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.uOsfp)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">Leaf ↔ Spine</span> MPO-MPO-OM4 <span className="st-name__sub">(2× per link)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.uMpo)}</td>)}
              </tr>
              <tr>
                <td className="st-name"><span className="st-seg st-seg--alt">Leaf ↔ Spine</span> 800G-OSFP <span className="st-name__sub">(spine-side)</span></td>
                {GB300_PROFILES.map((p) => <td key={p.gpus} className="st-num">{fmt(p.uOsfp2)}</td>)}
              </tr>
            </tbody>
          </table>
        </div>
        <div className="scale-table__legend">
          <span className="st-legend__item"><span className="st-dot st-dot--rail"></span>NIC ↔ Leaf · south, rack to fabric</span>
          <span className="st-legend__item"><span className="st-dot st-dot--upl"></span>Leaf ↔ Spine · north, full mesh</span>
          <span className="st-legend__item st-legend__note">2× MPO trunks per 800G link (2×400G internal). Substitute DR4 / LR4 for cross-hall reach.</span>
        </div>
      </div>
    </section>

    {/* Technical Notes by Layer */}
    <section className="art-section">
      <h3 className="art-h3">Layer-by-Layer Technical Notes</h3>

      <div className="art-tech-grid">
        <div className="art-tech">
          <div className="art-tech__k">NVL72 rack (GB300)</div>
          <div className="art-tech__body">
            <p><b>72 Blackwell Ultra GPUs</b> interconnected by NVSwitch trays. <b>NVLink 5</b> delivers <b>1.8 TB/s per GPU</b> intra-rack, <b>130 TB/s rack aggregate</b>. Integrated liquid cooling (CDU + manifold) is mandatory; per-rack envelope tracks <b>≥ 130 kW</b>.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">NIC layer</div>
          <div className="art-tech__body">
            <p><b>72 × ConnectX-8 / BlueField-3</b> NICs at <b>1 × 800G OSFP</b>, one per GPU on PCIe Gen6 ×16. GPUDirect RDMA, per-NIC PFC/ECN, and SR-IOV partitioning enabled. NIC BDF aligned to GPU NUMA / NVSwitch domain.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Leaf switch</div>
          <div className="art-tech__body">
            <p><b>64 × 800G TH5</b> (Tomahawk 5, 51.2 Tb/s). 32 ports south to NVL72 NICs, 32 ports north to Spine. <b>RoCEv2</b> with PFC + ECN; DCQCN tuned for the 800G loss‑less class.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Spine switch</div>
          <div className="art-tech__body">
            <p>Same 64 × 800G TH5 platform reused at Spine. Full mesh to Leaves; ECMP across N Spines provides bisection. At <b>24 Spines</b>, the 1,728 GPU pod sits in a single fabric domain.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Optics &amp; cabling</div>
          <div className="art-tech__body">
            <p><b>800G-OSFP</b> on both ends, joined by <b>2 × MPO-12 OM4</b> trunks per link (each carries one 400G half). SR8 reach ≤ 100 m on OM4. Cross-hall runs use <b>2× 400G-DR4</b> or <b>800G-DR8</b> single-mode.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Out-of-band &amp; storage</div>
          <div className="art-tech__body">
            <p>Dedicated <b>OOB management plane</b> (BMC, BCM, NetQ) on a separate 1G/10G fabric. <b>Storage fabric</b> on a dedicated DPU-attached plane — never folded into the compute RoCE plane.</p>
          </div>
        </div>
      </div>
    </section>
  </>;


/* ---------- Article 4: B300 + CX8 Dual-Port 400G Dual-Plane body ---------- */
const ArticleB300DualPlane = () =>
<>
    {/* Executive Summary */}
    <section className="art-section">
      <h3 className="art-h3">Executive Summary</h3>
      <p className="art-p">
        This reference architecture defines a <b>dual-plane, dual-port 400G RoCEv2 compute fabric</b> for
        NVIDIA <b>B300</b> GPU servers equipped with <b>ConnectX-8 (CX8)</b> dual-port 400G NICs. The
        design splits the scale-out fabric into <b>two physically and logically independent planes</b>
        (Plane 1, Plane 2) with a <b>Cross-Plane (CP) tier</b> bridging the two when bisection bandwidth
        is required. Each GPU server's NICs are bonded across both planes — <b>half the 400G ports land
        on Plane 1, half on Plane 2</b> — so the loss of an entire plane degrades, rather than halts,
        production training jobs.
      </p>
      <p className="art-p">
        The intent is <b>job-level fault tolerance for AI factory operators</b>: an unplanned spine, leaf,
        TOR, optic, or maintenance window on either plane removes capacity, not availability. NCCL
        topology hints, GPUDirect RDMA, and PFC/ECN are tuned per-plane so the collective scheduler
        re-routes survivors without restarting the job. Bisection between planes is provided by the
        Cross-Plane switches, which the collective uses only when a partition genuinely spans both
        planes — keeping the steady-state east-west pattern <b>plane-local and 1:1 non-blocking</b>.
      </p>
    </section>

    {/* Topology */}
    <section className="art-section">
      <h3 className="art-h3">Fabric Topology</h3>
      <p className="art-p">
        Three tiers per plane: <b>TOR → Leaf → Cross-Plane</b>. Within a plane, each block of GPU
        servers homes to a TOR cluster (8 TORs per cluster, 2 clusters per plane). Plane-internal
        bisection is delivered by a leaf row that full-meshes to its 16 plane TORs at 400G. The
        Cross-Plane tier sits above both plane-leaves and full-meshes <b>across</b> Plane 1 and Plane 2
        leaves — that is the only tier carrying inter-plane traffic. From the GPU NIC's perspective,
        the fabric is a flat plane-local L3 RoCE domain; ECMP across leaves and the CP layer is the
        sole multipath strategy.
      </p>
      <div className="art-figure">
        <iframe
        src="assets/network-topology-dualplane.html"
        title="B300 + CX8 Dual-Plane Network Topology"
        className="art-iframe art-iframe--tall"
        loading="lazy" />
      </div>
      <div className="art-callouts">
        <div className="art-callout">
          <div className="art-callout__k">Per-GPU bandwidth</div>
          <div className="art-callout__v">2 × 400G</div>
          <div className="art-callout__s">CX8 dual-port, split across both planes</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Plane survival</div>
          <div className="art-callout__v">50% on plane loss</div>
          <div className="art-callout__s">Job continues at half-bisection bandwidth</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Block scale</div>
          <div className="art-callout__v">4 blocks × 64 srv</div>
          <div className="art-callout__s">256 B300 servers, 2,048 GPUs per pod</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">East-west BW</div>
          <div className="art-callout__v">1:1 non-blocking</div>
          <div className="art-callout__s">Per plane; CP tier is bisection on demand</div>
        </div>
      </div>
    </section>

    {/* Dual-NIC, Dual-Plane Resilience Model */}
    <section className="art-section">
      <h3 className="art-h3">Dual-NIC, Dual-Plane Resilience Model</h3>
      <p className="art-p">
        Each <b>B300 GPU server</b> carries <b>8 × CX8 dual-port 400G NICs</b> (16 × 400G physical
        ports per server, 6.4 Tb/s of scale-out bandwidth). Ports are <b>striped across planes by
        physical NIC, not by logical link</b>: NIC<sub>1..4</sub> port-0 → Plane 1 TOR<sub>i</sub>, NIC<sub>1..4</sub>{' '}
        port-1 → Plane 2 TOR<sub>i</sub>; NIC<sub>5..8</sub> mirror this on the second TOR cluster. The
        result: any single TOR, leaf, CDU, or PDU failure removes at most one plane's worth of
        bandwidth for any affected server — never both. NCCL <b>NCCL_IB_HCA</b> + topology hints surface
        the plane label so the runtime ranks NICs by plane health before each step.
      </p>
      <div className="art-callouts">
        <div className="art-callout">
          <div className="art-callout__k">Plane failure mode</div>
          <div className="art-callout__v">Job continues</div>
          <div className="art-callout__s">No restart; reduced bandwidth, same step</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Maintenance window</div>
          <div className="art-callout__v">Plane drain</div>
          <div className="art-callout__s">Drain one plane, patch, return to service</div>
        </div>
        <div className="art-callout">
          <div className="art-callout__k">Blast radius</div>
          <div className="art-callout__v">≤ 50% BW</div>
          <div className="art-callout__s">Single fabric event, never &gt; one plane</div>
        </div>
      </div>
    </section>

    {/* Layer-by-Layer Technical Notes */}
    <section className="art-section">
      <h3 className="art-h3">Layer-by-Layer Technical Notes</h3>

      <div className="art-tech-grid">
        <div className="art-tech">
          <div className="art-tech__k">Compute node (B300)</div>
          <div className="art-tech__body">
            <p><b>8 × Blackwell Ultra (B300) SXM GPUs</b> per chassis with <b>NVLink 5 / NVSwitch</b> for
            intra-node collectives — <b>1.8 TB/s per GPU</b> NVLink bandwidth. Each GPU is paired 1:1
            with a <b>ConnectX-8 (CX8) dual-port 400G</b> NIC on <b>PCIe Gen6 ×16</b>, BDF-affined to
            the local NUMA. GPUDirect RDMA, per-NIC PFC/ECN, SR-IOV, and per-VF rate-limiting enabled.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">NIC layer (CX8 dual-port)</div>
          <div className="art-tech__body">
            <p>Each CX8 exposes <b>2 × 400G OSFP-RHS</b> ports as a single hardware function. Port-0
            homes to a <b>Plane 1 TOR</b>, port-1 to a <b>Plane 2 TOR</b>, never to the same plane. NCCL
            sees both as independent rails; <b>NCCL_CROSS_NIC=0</b> within plane, <b>=2</b> across
            planes so the runtime prefers plane-local paths and only crosses on bisection-bound
            collectives. PFC/ECN tuned per port; DCQCN profile pinned per plane.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">TOR switch (per-plane)</div>
          <div className="art-tech__body">
            <p><b>64 × 800G TH5</b> class platform (51.2 Tb/s, breakable to 128 × 400G). 64 × 400G ports
            south to 64 B300 servers (one port per server per plane), 64 × 400G north to plane Leaf.
            <b> RoCEv2 with PFC + ECN</b>, lossless on the GPU class, ECN-only on the storage class.
            Plane-local control plane — each plane runs its own BGP-EVPN/L3 RoCE domain.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Leaf switch (per-plane)</div>
          <div className="art-tech__body">
            <p>Same <b>64 × 800G TH5</b> platform reused at Leaf, configured as 128 × 400G logical ports.
            Within one plane: 16 TORs × 64 north-ports = 1,024 uplinks served by <b>8 Leaves × 128 ports</b>
            at 1:1. Inter-plane (Cross-Plane) uplinks are reserved on dedicated ports — never mixed
            with intra-plane bisection on the same port group.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Cross-Plane (CP) tier</div>
          <div className="art-tech__body">
            <p>The CP tier is the <b>only fabric element that physically connects Plane 1 and Plane 2</b>.
            <b> N × 64 × 800G TH5</b> CP switches full-mesh to <b>all</b> Leaves in both planes. ECMP
            across CP switches resolves any-source / any-destination bisection across planes. CP is
            sized for the realistic <b>cross-plane working set</b> — typically <b>1:2 oversubscribed</b>{' '}
            relative to plane-local capacity, since correctly-tuned NCCL keeps &gt; 90% of collective
            traffic plane-local.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Optics &amp; cabling</div>
          <div className="art-tech__body">
            <p><b>400G-OSFP-DR4</b> NIC-side for in-hall reach (≤ 500 m on single-mode), <b>400G-OSFP-SR4</b>
            on shorter MMF runs. Switch-side <b>800G-OSFP</b> split via <b>2 × MPO-12 OM4</b> for
            400G-DR breakouts, or <b>1 × MPO-16</b> for native 2 × 400G when leaf/TOR sits in adjacent
            rows. Plane separation is enforced physically — <b>distinct cable trays, distinct PDU
            feeds, distinct row groupings</b>.</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Power &amp; thermal</div>
          <div className="art-tech__body">
            <p>B300 server envelope <b>~14–16 kW</b> sustained at 8-GPU class load; per-rack density at
            6 servers/rack drives <b>≥ 90 kW</b> rack power. <b>Liquid-to-chip CDU</b> capacity at the
            row mandatory; redundant <b>415V/3-phase</b> feeds, A+B split between PDUs that
            <b> must not cross planes</b> (so a single PDU loss never blacks out both planes for a server).</p>
          </div>
        </div>
        <div className="art-tech">
          <div className="art-tech__k">Out-of-band &amp; storage</div>
          <div className="art-tech__body">
            <p>Dedicated <b>1G/10G OOB management plane</b> (BMC, BCM, NetQ) — itself dual-homed but kept
            off the compute fabric. <b>Storage fabric</b> on a separate DPU-attached plane (BlueField-3
            class) with its own switches; <b>storage is never folded into the compute RoCE plane</b>.</p>
          </div>
        </div>
      </div>
    </section>

    {/* Why Dual-Plane */}
    <section className="art-section">
      <h3 className="art-h3">Why Dual-Plane on B300 + CX8</h3>
      <p className="art-p">
        The B300 generation puts <b>2 × 400G per GPU</b> on the table at the NIC. A single-plane fabric
        would consume that bandwidth on a single failure domain; a dual-plane fabric spends it on
        <b> simultaneous bandwidth and resilience</b>. Three properties make this the right design
        for AI factory operators:
      </p>
      <ul className="art-list">
        <li><b>Plane-local 1:1 non-blocking.</b> Each plane is its own 1:1 Leaf-TOR fabric. NCCL keeps
        intra-job collectives plane-local; per-plane queue-pair scheduling avoids cross-plane HOL.</li>
        <li><b>Failure-budget alignment with training economics.</b> A multi-week training job that
        loses 50% of its scale-out bandwidth for a few hours is recoverable; a job that halts and
        restarts from the last checkpoint can cost a six-figure GPU-hour bill.</li>
        <li><b>Maintenance without windows.</b> Patch one plane while the other serves traffic. No
        change-window negotiation with the workload team, no overnight cutover.</li>
      </ul>
    </section>
  </>;


/* ---------- Articles registry ---------- */
const ARCH_ARTICLES = [
{
  id: 'h200-b200-rail',
  num: '01',
  kicker: 'Rail Architecture',
  title: 'H200 / B200 8-Rail Architecture',
  desc: 'Rail-aligned, non-blocking 400G RoCE fabric for H200 / B200 GPU servers. Scales 128 → 8,192 GPUs with deterministic BOM and a 1:1 leaf-spine design.',
  tags: ['H200', 'B200', '8-Rail', '400G RoCE', 'Leaf-Spine'],
  readTime: '12 min read',
  Body: ArticleH200B200
},
{
  id: 'gb200-nvl72-rail',
  num: '02',
  kicker: 'Rail Architecture',
  title: 'GB200 NVL72 4-Rail Architecture',
  desc: 'Rack-scale 4-rail RoCE fabric for GB200 NVL72 systems. 72-GPU NVLink racks fronted by 4 rail planes, scaling 144 → 6,912 GPUs at >120 kW/rack density.',
  tags: ['GB200', 'NVL72', '4-Rail', '400G RoCE', 'Rack-Scale'],
  readTime: '13 min read',
  Body: () => <ArticleGB200NVL72 />
},
{
  id: 'gb300-th5-800g',
  num: '03',
  kicker: 'Rail Architecture',
  title: 'RoCE GB300 NVL72 Architecture · TH5-800G',
  desc: 'Flat Spine–Leaf RoCE fabric on Broadcom TH5 64×800G switches for GB300 NVL72. 800G per GPU, no TOR layer, scaling 144 → 1,728 GPUs at 1:1 non-blocking.',
  tags: ['GB300', 'NVL72', 'TH5 800G', 'Spine-Leaf', '800G RoCE'],
  readTime: '12 min read',
  Body: () => <ArticleGB300TH5 />
},
{
  id: 'b300-cx8-dual-plane',
  num: '04',
  kicker: 'Dual-Plane Architecture',
  title: 'B300 & CX8 Dual-Port 400G, Dual-Plane Network',
  desc: 'Dual-plane 400G RoCE fabric for B300 GPU servers with ConnectX-8 dual-port NICs. Plane-isolated failure domains with Cross-Plane bisection — job-level resilience at AI-factory scale.',
  tags: ['B300', 'ConnectX-8', 'Dual-Plane', 'Dual-Port 400G', 'Cross-Plane'],
  readTime: '14 min read',
  Body: () => <ArticleB300DualPlane />
}];


const ArticlePlaceholder = ({ article }) =>
<div className="arch-canvas__placeholder">
    <div className="arch-canvas__ph-eyebrow">Article content</div>
    <p className="arch-canvas__ph-text">
      Technical article body for <b>{article.title}</b> will appear here.
      This canvas is scaffolded and ready to receive the architecture
      write-up — section headings, diagrams, tables, and reference notes.
    </p>
    <div className="arch-canvas__ph-blocks">
      <div className="arch-canvas__ph-block">
        <div className="arch-canvas__ph-label">§ 1 Overview</div>
        <div className="arch-canvas__ph-bar"></div>
        <div className="arch-canvas__ph-bar w80"></div>
        <div className="arch-canvas__ph-bar w60"></div>
      </div>
      <div className="arch-canvas__ph-block">
        <div className="arch-canvas__ph-label">§ 2 Diagram</div>
        <div className="arch-canvas__ph-diagram">Diagram / figure</div>
      </div>
    </div>
  </div>;


const ArticleCanvas = ({ article, onClose }) => {
  useEffect(() => {
    const onKey = (e) => e.key === 'Escape' && onClose();
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';

    // Auto-resize topology iframes to their content height
    const onMsg = (e) => {
      if (!e.data || e.data.type !== 'iframe-height') return;
      const iframes = document.querySelectorAll('.art-iframe');
      iframes.forEach((f) => {
        if (f.contentWindow === e.source) {
          const h = Math.max(120, Math.ceil(e.data.height || 0));
          f.style.height = h + 'px';
        }
      });
    };
    window.addEventListener('message', onMsg);

    return () => {
      document.removeEventListener('keydown', onKey);
      window.removeEventListener('message', onMsg);
      document.body.style.overflow = '';
    };
  }, [onClose]);

  const Body = article.Body;

  return (
    <div className="arch-canvas-backdrop" onClick={onClose} role="dialog" aria-modal="true" aria-label={article.title}>
      <aside className="arch-canvas" onClick={(e) => e.stopPropagation()}>
        <header className="arch-canvas__head">
          <div className="arch-canvas__meta">
            <span className="arch-canvas__num">{article.num} / 04</span>
            <span className="arch-canvas__kicker">{article.kicker}</span>
            <span className="arch-canvas__read">{article.readTime}</span>
          </div>
          <button className="arch-canvas__close" onClick={onClose} aria-label="Close article">
            <I.close />
          </button>
        </header>

        <div className="arch-canvas__body">
          <h2 className="arch-canvas__title">{article.title}</h2>
          <p className="arch-canvas__lede">{article.desc}</p>

          <div className="arch-canvas__tags">
            {article.tags.map((t) => <span key={t} className="tag">{t}</span>)}
          </div>

          {Body ? <Body /> : <ArticlePlaceholder article={article} />}
        </div>

        <footer className="arch-canvas__foot">
          <span className="arch-canvas__foot-meta">Click outside or press Esc to close</span>
          <a href="contact.html" className="btn btn-accent">Request a brief <I.arrow /></a>
        </footer>
      </aside>
    </div>);

};

const ArchArticleGrid = () => {
  const [open, setOpen] = useState(null);

  return (
    <section className="section">
      <div className="wrap">
        <div className="section-head reveal" style={{ marginBottom: 40 }}>
          <div className="eyebrow">Technical Articles / 01</div>
          <h2>Reference architecture, broken down.</h2>
          <p>Technical articles covering the full network design and intent architecture.</p>
        </div>

        <div className="arch-card-grid">
          {ARCH_ARTICLES.map((a, i) =>
          <article
            key={a.id}
            className={`arch-card reveal d${i % 4 + 1}`}
            onClick={() => setOpen(a)}
            role="button"
            tabIndex={0}
            onKeyDown={(e) => {
              if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                setOpen(a);
              }
            }}>
            
              <div className="arch-card__top">
                <span className="arch-card__num">{a.num}</span>
                <span className="arch-card__kicker">{a.kicker}</span>
              </div>
              <h3 className="arch-card__title">{a.title}</h3>
              <p className="arch-card__desc">{a.desc}</p>
              <div className="arch-card__tags">
                {a.tags.map((t) => <span key={t} className="tag">{t}</span>)}
              </div>
              <div className="arch-card__foot">
                <span className="arch-card__read">{a.readTime}</span>
                <span className="arch-card__cta">Read article <I.arrow /></span>
              </div>
            </article>
          )}
        </div>
      </div>
      {open && <ArticleCanvas article={open} onClose={() => setOpen(null)} />}
    </section>);

};

function ArchitectureApp() {
  useReveal();
  return (
    <>
      <Nav />
      <main>
        <PageHero
          eyebrow="Reference Architecture"
          crumbs={[
          { label: 'Home', href: 'index.html' },
          { label: 'Solutions', href: 'solutions.html' },
          { label: 'NVIDIA GPU Compute Network' }]
          }
          title={<>NVIDIA GPU Compute Network <span className="accent">Reference Architecture.</span></>}
          sub="A blueprint for high-performance GPU compute fabrics — compute, storage, and management plane wired for production AI workloads at scale." />
        

        <ArchArticleGrid />

        <CTABanner
          title="Want to deploy this architecture in your environment?"
          sub="Tell us about your target cluster size, power envelope, and timeline. We'll come back with a tailored deployment plan."
          primary="Request a brief"
          primaryHref="contact.html"
          secondary="Back to solutions"
          secondaryHref="solutions.html" />
        
      </main>
      <Footer />
    </>);

}

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