{
  "name": "gpu-infrastructure-default",
  "type": "registry:block",
  "tier": "free",
  "dependencies": [],
  "registryDependencies": [
    "https://www.craftui.space/r/craftui-base.json"
  ],
  "files": [
    {
      "path": "components/craftui/illustrations/gpu-infrastructure/default.tsx",
      "content": "// Extracted from the feature-ai-01 section, where this diagram anchors the\n// header. Registry items ship as one self-contained file to a consumer's\n// project, so the isometric helpers below are duplicated here rather than\n// imported from the section — a shared module would arrive as a second file the\n// consumer never asked for, and a dangling import if they install only one.\n//\n// No motion: the diagram is drawn once and holds still.\n\ninterface GpuInfrastructureProps {\n  /** Additional classes on the <svg> root. */\n  className?: string;\n}\n\n// ─── Isometric projection ─────────────────────────────────────────────────────\n//\n// A true 2:1 isometric would use k = 0.5; 0.866 (cos 30°) gives the taller,\n// squarer cabinet look. ISO_S is the unit size in px, ISO_OX/OY the origin —\n// tuned so the finished stack sits centred in the 420×450 viewBox.\n\nconst ISO_K = 0.8660254;\nconst ISO_S = 13;\nconst ISO_OX = 190;\nconst ISO_OY = 250;\n\ntype Pt = readonly [number, number];\n\nconst p = (x: number, y: number, z = 0): Pt => [\n  (x - y) * ISO_K * ISO_S + ISO_OX,\n  ((x + y) / 2 - z) * ISO_S + ISO_OY,\n];\n\nconst poly = (pts: Pt[], close = true) =>\n  pts\n    .map(([x, y], i) => `${i ? \"L\" : \"M\"}${x.toFixed(2)} ${y.toFixed(2)}`)\n    .join(\" \") + (close ? \"Z\" : \"\");\n\n/**\n * Same as poly(), but every corner is cut back by `r` and rejoined with a\n * quadratic through the original vertex. Rounding the projected polygon rather\n * than applying a corner radius in 3D is what keeps the bevel visually equal on\n * all three faces — the faces are foreshortened differently, so a radius\n * applied before projection would come out uneven.\n */\nconst roundPoly = (pts: Pt[], r = 2) => {\n  const n = pts.length;\n  const lerp = (a: Pt, b: Pt, t: number): Pt => [\n    a[0] + (b[0] - a[0]) * t,\n    a[1] + (b[1] - a[1]) * t,\n  ];\n  const at = (a: Pt, b: Pt) => {\n    const len = Math.hypot(b[0] - a[0], b[1] - a[1]);\n    return Math.min(0.5, r / (len || 1));\n  };\n  let d = \"\";\n  for (let i = 0; i < n; i++) {\n    const prev = pts[(i - 1 + n) % n];\n    const cur = pts[i];\n    const next = pts[(i + 1) % n];\n    const a = lerp(cur, prev, at(cur, prev));\n    const b = lerp(cur, next, at(cur, next));\n    d +=\n      i === 0\n        ? `M${a[0].toFixed(2)} ${a[1].toFixed(2)}`\n        : `L${a[0].toFixed(2)} ${a[1].toFixed(2)}`;\n    d += `Q${cur[0].toFixed(2)} ${cur[1].toFixed(2)} ${b[0].toFixed(2)} ${b[1].toFixed(2)}`;\n  }\n  return d + \"Z\";\n};\n\nconst quad = (x: number, y: number, z: number, w: number, d: number) =>\n  [p(x, y, z), p(x + w, y, z), p(x + w, y + d, z), p(x, y + d, z)] as Pt[];\n\n/** The three faces of a box that are visible from this camera. */\nconst boxFaces = (\n  x: number,\n  y: number,\n  z: number,\n  w: number,\n  d: number,\n  h: number,\n) => ({\n  top: quad(x, y, z + h, w, d),\n  front: [\n    p(x, y + d, z),\n    p(x + w, y + d, z),\n    p(x + w, y + d, z + h),\n    p(x, y + d, z + h),\n  ] as Pt[],\n  flank: [\n    p(x + w, y, z),\n    p(x + w, y + d, z),\n    p(x + w, y + d, z + h),\n    p(x + w, y, z + h),\n  ] as Pt[],\n});\n\n/** A rectangle lying flat on the front face, for vents and ports. */\nconst onFront = (yc: number, x0: number, x1: number, z0: number, z1: number) =>\n  [p(x0, yc, z0), p(x1, yc, z0), p(x1, yc, z1), p(x0, yc, z1)] as Pt[];\n\n/** The same, on the right-hand flank. */\nconst onFlank = (xc: number, y0: number, y1: number, z0: number, z1: number) =>\n  [p(xc, y0, z0), p(xc, y1, z0), p(xc, y1, z1), p(xc, y0, z1)] as Pt[];\n\nconst range = (n: number) => Array.from({ length: n }, (_, i) => i);\n\n// ─── Ink ──────────────────────────────────────────────────────────────────────\n//\n// Neutral greys, no hue at all: white in light, black in dark, three steps of\n// it for the three faces, lightest on top. The shading is doing the work a light\n// source would, so the solid never needs a gradient to read as solid, and the\n// accent is a mid grey that separates from every face in both themes.\n//\n// Every colour is a class pair rather than a fill/stroke attribute, because an\n// attribute cannot answer to the theme. In dark the faces darken and the ink\n// lifts, but the light keeps coming from the same place — the top face is still\n// the lightest of the three, so the solid reads the same way in both themes.\n//\n// Classes rather than cssVars on purpose: cssVars are written into a consumer's\n// stylesheet at install time, so they do nothing for the copy rendering from\n// source in this repo's own gallery. This travels with the file. CSS beats a\n// presentation attribute, so the fill=\"none\" left on the <svg> root does not\n// fight them.\n\nconst INK = \"stroke-[#1A1A1A] dark:stroke-[#A8A8A8] dark:stroke-opacity-[0.9]\";\nconst ACCENT = \"fill-[#6B6B6B] dark:fill-[#B4B4B4]\";\nconst TOP = \"fill-[#FFFFFF] dark:fill-[#3A3A3A]\";\nconst FRONT = \"fill-[#EFEFEF] dark:fill-[#2A2A2A]\";\nconst FLANK = \"fill-[#DADADA] dark:fill-[#1C1C1C]\";\n\nconst LINE = {\n  fill: \"none\",\n  strokeLinejoin: \"round\",\n} as const;\n\n/**\n * The dashed footprint and rack posts are drawn straight onto the page rather\n * than onto a face, so they are the only marks that meet the background\n * directly. They flip like the rest of the ink, but land short of it — a step\n * in from the full lift — which keeps the guides subordinate to the outlines in\n * both themes. The opacity rises a little in dark because a light ink on a dark\n * ground reads fainter than the reverse at equal alpha.\n */\nconst GUIDE_INK =\n  \"stroke-[#1A1A1A] opacity-[0.3] dark:stroke-[#A8A8A8] dark:opacity-[0.45]\";\n\n/** One compute unit in the stack. `index` fades the accent bar with depth. */\nfunction DataBox({ z, index }: { z: number; index: number }) {\n  const x = 0,\n    y = 0,\n    w = 11,\n    d = 8,\n    h = 2.3;\n  const f = boxFaces(x, y, z, w, d, h);\n  const yf = y + d;\n\n  return (\n    <g>\n      {/* Fills first, then detail, then the heavy outline on top — the outline\n          has to overdraw the vent hatching where they meet. */}\n      <path d={roundPoly(f.flank)} className={FLANK} />\n      <path d={roundPoly(f.front)} className={FRONT} />\n      <path d={roundPoly(f.top)} className={TOP} />\n\n      <g {...LINE} className={INK} strokeWidth={0.75} opacity={0.45}>\n        {range(10).map((i) => {\n          const gx = 0.7 + i * 0.7;\n          return (\n            <path\n              key={i}\n              d={poly(onFront(yf, gx, gx + 0.4, z + 0.5, z + 1.8))}\n            />\n          );\n        })}\n        <path\n          d={roundPoly(\n            onFlank(x + w, y + 1.1, y + d - 1.1, z + 0.6, z + 1.7),\n            2,\n          )}\n        />\n        <path d={roundPoly(quad(x + 0.5, y + 0.5, z + h, w - 1, d - 1), 2)} />\n      </g>\n\n      <g {...LINE} className={INK} strokeWidth={1.3}>\n        <path d={roundPoly(f.flank)} />\n        <path d={roundPoly(f.front)} />\n        <path d={roundPoly(f.top)} />\n      </g>\n    </g>\n  );\n}\n\nexport function GpuInfrastructure({ className }: GpuInfrastructureProps) {\n  const w = 11,\n    d = 8;\n  const edges = [\n    [0, d],\n    [w, d],\n    [w, 0],\n  ] as const;\n  const levels = [0, 6, 12];\n  const plinth = boxFaces(-2.2, -2.2, -0.9, w + 4.4, d + 4.4, 0.9);\n\n  return (\n    // viewBox-driven with no width/height attributes, so the diagram fills\n    // whatever box its container reserves and scales down instead of\n    // overflowing.\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 420 450\"\n      className={className}\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      role=\"img\"\n      aria-label=\"Isometric diagram: three stacked GPU compute units on a plinth\"\n    >\n      {/* Plinth */}\n      <g>\n        <path d={roundPoly(plinth.flank)} className={FLANK} />\n        <path d={roundPoly(plinth.front)} className={FRONT} />\n        <path d={roundPoly(plinth.top)} className={TOP} />\n        <g {...LINE} className={INK} strokeWidth={0.8}>\n          <path d={roundPoly(plinth.flank)} />\n          <path d={roundPoly(plinth.front)} />\n          <path d={roundPoly(plinth.top)} />\n        </g>\n      </g>\n\n      {/* Rack posts, drawn before the units so each one occludes them */}\n      {/* <g strokeWidth={1} strokeDasharray=\"4 6\" className={GUIDE_INK}>\n        {edges.map(([ex, ey], i) => {\n          const a = p(ex, ey, 0);\n          const b = p(ex, ey, levels[2] + 2.3);\n          return <path key={i} d={`M${a[0]} ${a[1]}V${b[1]}`} />;\n        })}\n      </g> */}\n\n      {/* Painter's algorithm: lowest z first, so upper units overlap correctly */}\n      {levels.map((z, i) => (\n        <DataBox key={z} z={z} index={levels.length - 1 - i} />\n      ))}\n\n      {/* Cable terminations on the front-left corner post */}\n      {/* <g className={ACCENT} stroke=\"none\" opacity={0.6}>\n        {[4.4, 10.4].map((z) => {\n          const a = p(0, d, z);\n          return <circle key={z} cx={a[0]} cy={a[1]} r={2.6} />;\n        })}\n      </g> */}\n    </svg>\n  );\n}\n",
      "type": "registry:component",
      "target": "~/components/craftui/illustrations/gpu-infrastructure/default.tsx"
    }
  ],
  "meta": {
    "displayName": "GPU Infrastructure - GPU Infrastructure",
    "description": "An isometric compute stack — three GPU units racked on a plinth inside a dashed footprint. For AI, GPU and developer-infrastructure pages that need a picture of the machine.",
    "category": "infrastructure",
    "tags": [
      "illustration",
      "isometric",
      "infrastructure",
      "gpu",
      "compute",
      "diagram",
      "svg",
      "static"
    ],
    "animationType": "none"
  }
}