{
  "name": "feature-ai-01-default",
  "type": "registry:block",
  "tier": "free",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://www.craftui.space/r/craftui-base.json",
    "badge",
    "button",
    "card",
    "separator"
  ],
  "files": [
    {
      "path": "components/craftui/sections/feature-ai-01/default.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n  AnimatePresence,\n  MotionConfig,\n  motion,\n  useInView,\n  useReducedMotion,\n} from \"motion/react\";\n\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from \"@/components/ui/accordion\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\n\nconst TAU = Math.PI * 2;\nconst INK = \"#111111\";\n\nconst clamp01 = (t: number) => (t < 0 ? 0 : t > 1 ? 1 : t);\nconst frac = (t: number) => t - Math.floor(t);\n\nconst tri = (t: number) => 1 - Math.abs(2 * frac(t) - 1);\n\nconst wrapDist = (t: number) => {\n  const f = frac(t);\n  return f < 0.5 ? f : 1 - f;\n};\n\nconst smootherstep = (t: number) => {\n  const x = clamp01(t);\n  return x * x * x * (x * (x * 6 - 15) + 10);\n};\n\nconst impulse = (t: number, k = 12) => {\n  const h = k * t;\n  return h * Math.exp(1 - h);\n};\n\nfunction roundRect(\n  p: Path2D,\n  x: number,\n  y: number,\n  w: number,\n  h: number,\n  r: number,\n) {\n  const rad = Math.min(r, Math.abs(w) / 2, Math.abs(h) / 2);\n  p.moveTo(x + rad, y);\n  p.arcTo(x + w, y, x + w, y + h, rad);\n  p.arcTo(x + w, y + h, x, y + h, rad);\n  p.arcTo(x, y + h, x, y, rad);\n  p.arcTo(x, y, x + w, y, rad);\n  p.closePath();\n}\n\nfunction lazy<T>(make: () => T) {\n  let v: T | undefined;\n  return () => (v === undefined ? (v = make()) : v);\n}\n\ntype Deriv = (t: number, y: Float64Array, out: Float64Array) => void;\n\nfunction makeRK4(n: number, f: Deriv) {\n  const k1 = new Float64Array(n);\n  const k2 = new Float64Array(n);\n  const k3 = new Float64Array(n);\n  const k4 = new Float64Array(n);\n  const yt = new Float64Array(n);\n  return (y: Float64Array, t: number, dt: number) => {\n    f(t, y, k1);\n    for (let i = 0; i < n; i++) yt[i] = y[i] + (dt / 2) * k1[i];\n    f(t + dt / 2, yt, k2);\n    for (let i = 0; i < n; i++) yt[i] = y[i] + (dt / 2) * k2[i];\n    f(t + dt / 2, yt, k3);\n    for (let i = 0; i < n; i++) yt[i] = y[i] + dt * k3[i];\n    f(t + dt, yt, k4);\n    for (let i = 0; i < n; i++)\n      y[i] += (dt / 6) * (k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]);\n  };\n}\n\nfunction closeDrift(frames: Float64Array[]): Float64Array[] {\n  const n = frames.length;\n  const dim = frames[0].length;\n  for (let j = 0; j < dim; j++) {\n    const drift = frames[n - 1][j] - frames[0][j];\n    for (let i = 0; i < n; i++) frames[i][j] -= (i / (n - 1)) * drift;\n  }\n  return frames.slice(0, n - 1);\n}\n\nfunction sampleFrames(frames: Float64Array[], tau: number, out: Float64Array) {\n  const n = frames.length;\n  const x = frac(tau) * n;\n  const i0 = Math.floor(x) % n;\n  const i1 = (i0 + 1) % n;\n  const f = x - Math.floor(x);\n  const a = frames[i0];\n  const b = frames[i1];\n  for (let j = 0; j < out.length; j++) out[j] = a[j] * (1 - f) + b[j] * f;\n}\n\nconst lorenzDeriv: Deriv = (t, y, o) => {\n  o[0] = 10 * (y[1] - y[0]);\n  o[1] = y[0] * (28 - y[2]) - y[1];\n  o[2] = y[0] * y[1] - (8 / 3) * y[2];\n};\n\nconst lorenzUPO = lazy(() => {\n  const step = makeRK4(3, lorenzDeriv);\n  const y = Float64Array.from([1, 1, 20]);\n  const dt = 0.002;\n  for (let i = 0; i < 15000; i++) step(y, 0, dt);\n\n  const sect: { x: number; y: number; t: number; s: Float64Array }[] = [];\n  let t = 0;\n  for (let i = 0; i < 900000 && sect.length < 2200; i++) {\n    const pz = y[2];\n    step(y, t, dt);\n    t += dt;\n    if (pz < 27 && y[2] >= 27)\n      sect.push({ x: y[0], y: y[1], t, s: Float64Array.from(y) });\n  }\n\n  let best = 0;\n  let bd = Infinity;\n  for (let i = 0; i + 2 < sect.length; i++) {\n    const d = Math.hypot(sect[i].x - sect[i + 2].x, sect[i].y - sect[i + 2].y);\n    if (d < bd) {\n      bd = d;\n      best = i;\n    }\n  }\n\n  const T = sect[best + 2].t - sect[best].t;\n  const N = 900;\n  const h = T / N;\n  const s = Float64Array.from(sect[best].s);\n  const raw: Float64Array[] = [];\n  for (let i = 0; i <= N; i++) {\n    raw.push(Float64Array.from(s));\n    if (i < N) step(s, 0, h);\n  }\n  return { frames: closeDrift(raw), T, err: bd };\n});\n\nexport type Art = {\n  id: string;\n  name: string;\n  period: number;\n  fps?: number;\n  draw: (ctx: CanvasRenderingContext2D, size: number, tau: number) => void;\n};\n\nconst flow: Art = {\n  id: \"flow\",\n  name: \"Flow\",\n  period: 9,\n  draw(ctx, size, tau) {\n    const n = 30;\n    const cell = size / n;\n    const len = cell * 0.78;\n    const path = new Path2D();\n\n    for (let j = 0; j < n; j++) {\n      for (let i = 0; i < n; i++) {\n        const xn = i / (n - 1);\n        const yn = j / (n - 1);\n        const a =\n          TAU *\n          (0.45 * Math.sin(TAU * (1.1 * xn - tau)) +\n            0.35 * Math.cos(TAU * (1.3 * yn + tau)) +\n            0.3 * Math.sin(TAU * (0.9 * (xn + yn) - 2 * tau)));\n        const s = 0.45 + 0.55 * impulse(frac(tau + (xn + yn) * 0.5), 3);\n        const l = (len / 2) * Math.min(1.3, s);\n        const cx = (i + 0.5) * cell;\n        const cy = (j + 0.5) * cell;\n        path.moveTo(cx - l * Math.cos(a), cy - l * Math.sin(a));\n        path.lineTo(cx + l * Math.cos(a), cy + l * Math.sin(a));\n      }\n    }\n    ctx.lineCap = \"round\";\n    ctx.lineWidth = cell * 0.2;\n    ctx.strokeStyle = INK;\n    ctx.stroke(path);\n  },\n};\n\nconst pulse: Art = {\n  id: \"pulse\",\n  name: \"Pulse\",\n  period: 5,\n  draw(ctx, size, tau) {\n    const n = 16;\n    const cell = size / n;\n    const rMax = cell * 0.46;\n    const sigma = 0.11;\n    const path = new Path2D();\n\n    for (let j = 0; j < n; j++) {\n      for (let i = 0; i < n; i++) {\n        const u = (i + j) / (2 * (n - 1));\n        const a = wrapDist(tau - u);\n        const b = wrapDist(tau - u + 0.5);\n        const g =\n          Math.exp(-(a * a) / (2 * sigma * sigma)) +\n          0.55 * Math.exp(-(b * b) / (2 * sigma * sigma));\n        const r = rMax * (0.14 + 0.86 * Math.min(1, g));\n        path.moveTo((i + 0.5) * cell + r, (j + 0.5) * cell);\n        path.arc((i + 0.5) * cell, (j + 0.5) * cell, r, 0, TAU);\n      }\n    }\n    ctx.fillStyle = INK;\n    ctx.fill(path);\n  },\n};\n\nconst columns: Art = {\n  id: \"columns\",\n  name: \"Columns\",\n  period: 6,\n  draw(ctx, size, tau) {\n    const n = 13;\n    const cell = size / n;\n    const bw = cell * 0.46;\n    const path = new Path2D();\n\n    for (let j = 0; j < n; j++) {\n      for (let i = 0; i < n; i++) {\n        const u = (i + j) / (2 * (n - 1));\n        const h = 0.1 + 0.9 * smootherstep(tri(tau - u));\n        const bh = cell * 0.9 * h;\n        const x = i * cell + (cell - bw) / 2;\n        const y = j * cell + cell * 0.95 - bh;\n        roundRect(path, x, y, bw, bh, bw * 0.5);\n      }\n    }\n    ctx.fillStyle = INK;\n    ctx.fill(path);\n  },\n};\n\nconst lorenzOrbit: Art = {\n  id: \"lorenz-upo\",\n  name: \"Lorenz orbit\",\n  period: 7,\n  draw(ctx, size, tau) {\n    const { frames } = lorenzUPO();\n    const s = size / 60;\n    const px = (v: number) => size / 2 + v * s;\n    const pz = (v: number) => size * 0.95 - v * s * 0.86;\n\n    ctx.strokeStyle = INK;\n    ctx.lineWidth = Math.max(0.6, size * 0.0035);\n    ctx.globalAlpha = 0.28;\n    ctx.beginPath();\n    for (let i = 0; i < frames.length; i++) {\n      const f = frames[i];\n      if (i === 0) ctx.moveTo(px(f[0]), pz(f[2]));\n      else ctx.lineTo(px(f[0]), pz(f[2]));\n    }\n    ctx.closePath();\n    ctx.stroke();\n    ctx.globalAlpha = 1;\n\n    const M = 26;\n    const p = new Float64Array(3);\n    const path = new Path2D();\n    for (let k = 0; k < M; k++) {\n      sampleFrames(frames, tau + k / M, p);\n      const sp = Math.hypot(10 * (p[1] - p[0]), p[0] * p[1] - (8 / 3) * p[2]);\n      const r = size * 0.006 + size * 0.016 * clamp01(sp / 260);\n      path.moveTo(px(p[0]) + r, pz(p[2]));\n      path.arc(px(p[0]), pz(p[2]), r, 0, TAU);\n    }\n    ctx.fillStyle = INK;\n    ctx.fill(path);\n  },\n};\n\nconst dipole: Art = {\n  id: \"dipole\",\n  name: \"Dipole field\",\n  period: 10,\n  draw(ctx, size, tau) {\n    const n = 24;\n    const cell = size / n;\n    const a = TAU * tau;\n    const poles = [\n      { x: size * 0.32, y: size * 0.38, mx: Math.cos(a), my: Math.sin(a) },\n      {\n        x: size * 0.68,\n        y: size * 0.64,\n        mx: Math.cos(-2 * a),\n        my: Math.sin(-2 * a),\n      },\n    ];\n    const path = new Path2D();\n    for (let j = 0; j < n; j++) {\n      for (let i = 0; i < n; i++) {\n        const px = (i + 0.5) * cell;\n        const py = (j + 0.5) * cell;\n        let bx = 0;\n        let by = 0;\n        for (const p of poles) {\n          const dx = (px - p.x) / size;\n          const dy = (py - p.y) / size;\n          const r = Math.max(0.04, Math.hypot(dx, dy));\n          const rx = dx / r;\n          const ry = dy / r;\n          const mr = p.mx * rx + p.my * ry;\n          const k = 1 / (r * r * r);\n          bx += k * (3 * mr * rx - p.mx);\n          by += k * (3 * mr * ry - p.my);\n        }\n        const ang = Math.atan2(by, bx);\n        const mag = Math.hypot(bx, by);\n        const L = cell * 0.46 * clamp01(0.25 + Math.log1p(mag) / 6);\n        path.moveTo(px - L * Math.cos(ang), py - L * Math.sin(ang));\n        path.lineTo(px + L * Math.cos(ang), py + L * Math.sin(ang));\n      }\n    }\n    ctx.lineCap = \"round\";\n    ctx.lineWidth = cell * 0.19;\n    ctx.strokeStyle = INK;\n    ctx.stroke(path);\n  },\n};\n\nconst lorenzSlice: Art = {\n  id: \"lorenz-slice\",\n  name: \"Lorenz slice\",\n  period: 13,\n  draw(ctx, size, tau) {\n    const n = 26;\n    const cell = size / n;\n    const phi = TAU * tau;\n    const cf = Math.cos(phi);\n    const sf = Math.sin(phi);\n    const S = 46;\n    const d = new Float64Array(3);\n    const s = new Float64Array(3);\n    const path = new Path2D();\n\n    for (let j = 0; j < n; j++) {\n      for (let i = 0; i < n; i++) {\n        const p = ((i + 0.5) / n - 0.5) * S;\n        const q = (0.5 - (j + 0.5) / n) * S + 25 + 7 * (1 - Math.cos(phi));\n        s[0] = p * cf;\n        s[1] = p * sf;\n        s[2] = q;\n        lorenzDeriv(0, s, d);\n        const vp = d[0] * cf + d[1] * sf;\n        const vq = d[2];\n        const ang = Math.atan2(-vq, vp);\n        const mag = Math.hypot(vp, vq);\n        const L = cell * 0.46 * clamp01(0.2 + Math.log1p(mag) / 6);\n        const cx = (i + 0.5) * cell;\n        const cy = (j + 0.5) * cell;\n        path.moveTo(cx - L * Math.cos(ang), cy - L * Math.sin(ang));\n        path.lineTo(cx + L * Math.cos(ang), cy + L * Math.sin(ang));\n      }\n    }\n    ctx.lineCap = \"round\";\n    ctx.lineWidth = cell * 0.18;\n    ctx.strokeStyle = INK;\n    ctx.stroke(path);\n  },\n};\n\nfunction OpCanvas({\n  draw,\n  period,\n  fps,\n  label,\n  className,\n}: {\n  draw: Art[\"draw\"];\n  period: number;\n  fps?: number;\n  label: string;\n  className?: string;\n}) {\n  const ref = useRef<HTMLCanvasElement>(null);\n  const reducedMotion = useReducedMotion();\n\n  useEffect(() => {\n    const canvas = ref.current;\n    if (!canvas) return;\n    const ctx = canvas.getContext(\"2d\");\n    if (!ctx) return;\n\n    let size = 0;\n    let raf = 0;\n    let last = -Infinity;\n    const start = performance.now();\n    const interval = fps ? 1000 / fps : 0;\n\n    const render = (now: number) => {\n      raf = window.requestAnimationFrame(render);\n      if (now - last < interval) return;\n      last = now;\n      const tau = reducedMotion ? 0 : frac((now - start) / 1000 / period);\n      ctx.clearRect(0, 0, size, size);\n      ctx.save();\n      draw(ctx, size, tau);\n      ctx.restore();\n    };\n\n    const stop = () => {\n      if (raf !== 0) window.cancelAnimationFrame(raf);\n      raf = 0;\n    };\n\n    const resize = () => {\n      const rect = canvas.getBoundingClientRect();\n      const box = Math.min(rect.width, rect.height);\n      if (box === 0) {\n        size = 0;\n        stop();\n        return;\n      }\n      const dpr = Math.min(2, window.devicePixelRatio || 1);\n      size = box;\n      canvas.width = Math.round(size * dpr);\n      canvas.height = Math.round(size * dpr);\n      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n      last = -Infinity;\n      if (raf === 0) raf = window.requestAnimationFrame(render);\n    };\n\n    const observer = new ResizeObserver(resize);\n    observer.observe(canvas);\n    resize();\n\n    return () => {\n      stop();\n      observer.disconnect();\n    };\n  }, [draw, period, fps, reducedMotion]);\n\n  return (\n    <canvas\n      ref={ref}\n      role=\"img\"\n      aria-label={label}\n      className={cn(\"block h-full w-full\", className)}\n    />\n  );\n}\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\nconst roundPoly = (pts: Pt[], r = 4) => {\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\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\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\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\nconst ISO_INK = \"#243027\";\nconst ACCENT = \"#6f7a62\";\nconst TOP = \"#ffffff\";\nconst FRONT = \"#f3f4f0\";\nconst FLANK = \"#e3e5de\";\n\nconst LINE = {\n  stroke: ISO_INK,\n  fill: \"none\",\n  strokeLinejoin: \"round\",\n} as const;\n\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      <path d={roundPoly(f.flank)} fill={FLANK} />\n      <path d={roundPoly(f.front)} fill={FRONT} />\n      <path d={roundPoly(f.top)} fill={TOP} />\n\n      <g {...LINE} strokeWidth={0.75} opacity={0.45}>\n        {range(16).map((i) => {\n          const gx = 0.7 + i * 0.42;\n          return (\n            <path\n              key={i}\n              d={poly(onFront(yf, gx, gx + 0.2, z + 0.5, z + 1.8))}\n            />\n          );\n        })}\n        <path d={roundPoly(onFront(yf, 7.9, 9.1, z + 0.5, z + 1.8), 2)} />\n        <path d={roundPoly(onFront(yf, 9.4, 10.4, z + 0.5, z + 1.8), 2)} />\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), 3)} />\n      </g>\n\n      <path\n        d={poly(onFront(yf, 0.7, 7.1, z + 2.0, z + 2.15))}\n        fill={ACCENT}\n        opacity={0.85 - index * 0.25}\n      />\n\n      <g {...LINE} 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\nfunction GpuInfrastructure({ className }: { className?: string }) {\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    <svg\n      viewBox=\"0 0 420 450\"\n      className={cn(\"h-auto w-full\", className)}\n      fill=\"none\"\n      stroke={ISO_INK}\n      strokeLinecap=\"round\"\n      role=\"img\"\n      aria-label=\"Isometric diagram: three stacked GPU compute units on a plinth\"\n    >\n      <path\n        d={roundPoly(quad(-4, -4, 0, w + 8, d + 8), 14)}\n        strokeWidth={1}\n        strokeDasharray=\"6 7\"\n        opacity={0.3}\n      />\n\n      <g>\n        <path d={roundPoly(plinth.flank)} fill={FLANK} />\n        <path d={roundPoly(plinth.front)} fill={FRONT} />\n        <path d={roundPoly(plinth.top)} fill={TOP} />\n        <g {...LINE} strokeWidth={1.3}>\n          <path d={roundPoly(plinth.flank)} />\n          <path d={roundPoly(plinth.front)} />\n          <path d={roundPoly(plinth.top)} />\n        </g>\n      </g>\n\n      <g strokeWidth={1} strokeDasharray=\"4 6\" opacity={0.32}>\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      {levels.map((z, i) => (\n        <DataBox key={z} z={z} index={levels.length - 1 - i} />\n      ))}\n\n      <g fill={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\nexport type Capability = {\n  word: string;\n  art: Art;\n  copy: string;\n};\n\nexport const FEATURE_AI_ART = {\n  flow,\n  pulse,\n  columns,\n  lorenzOrbit,\n  dipole,\n  lorenzSlice,\n} as const;\n\nexport const DEFAULT_CAPABILITIES: Capability[] = [\n  {\n    word: \"Throughput\",\n    art: flow,\n    copy: \"Continuous batching, paged attention, and speculative decoding land more tokens per GPU-second. Same weights, same hardware — up to 3.4× the requests served before you add a single node.\",\n  },\n  {\n    word: \"Latency\",\n    art: pulse,\n    copy: \"Weights stay resident and KV cache stays warm, so there is no cold start to pay for. Sub-200ms time-to-first-token at p99, measured under load rather than on an idle cluster.\",\n  },\n  {\n    word: \"Scale\",\n    art: columns,\n    copy: \"Autoscaling that reads queue depth instead of CPU, from one replica to four hundred across regions. Traffic spikes are absorbed in seconds, and idle capacity is released just as fast.\",\n  },\n  {\n    word: \"Reliability\",\n    art: lorenzOrbit,\n    copy: \"99.99% uptime, multi-region failover, and automatic node drain on hardware faults. In-flight requests are rescheduled, not dropped — an unhealthy GPU never becomes your incident.\",\n  },\n  {\n    word: \"Observability\",\n    art: dipole,\n    copy: \"Every request traced end to end: token counts, cache hit rate, queue time, and per-tenant spend. You see exactly which prompt shape is costing you, down to the individual call.\",\n  },\n  {\n    word: \"Sovereignty\",\n    art: lorenzSlice,\n    copy: \"Run in our cloud, your VPC, or fully air-gapped on your own metal — one control plane, one API. Your weights and your data never leave the perimeter you define.\",\n  },\n];\n\nconst GRAIN =\n  \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E\\\")\";\n\nconst CARD_GRADIENT = [\n  \"radial-gradient(72% 92% at 6% 6%, rgba(255,255,255,0.28), rgba(255,255,255,0) 62%)\",\n  \"linear-gradient(148deg, #5d6a4f 0%, #414b39 40%, #2b3425 74%, #1f271b 100%)\",\n].join(\",\");\n\nconst EASE_OUT = [0.22, 1, 0.36, 1] as const;\nconst EASE_IN = [0.4, 0, 1, 1] as const;\nconst ROLL = { type: \"spring\", visualDuration: 0.35, bounce: 0 } as const;\n\nconst STAGGER = { art: 0, label: 0.06, copy: 0.14 };\n\nconst AUTOPLAY_MS = 4000;\n\nfunction Marker({ active }: { active: boolean }) {\n  return (\n    <span className=\"relative mr-4 inline-flex h-1.5 w-1.5 shrink-0 items-center justify-center sm:mr-6\">\n      {active && (\n        <motion.span\n          layoutId=\"feature-ai-01-marker\"\n          transition={{\n            type: \"spring\",\n            stiffness: 520,\n            damping: 42,\n            mass: 0.6,\n          }}\n          className=\"absolute inset-0 rounded-full bg-neutral-900\"\n        />\n      )}\n    </span>\n  );\n}\n\nexport type FeatureAi01Props = {\n  capabilities?: Capability[];\n  autoplayMs?: number;\n  className?: string;\n};\n\nexport default function FeatureAi01({\n  capabilities = DEFAULT_CAPABILITIES,\n  autoplayMs = AUTOPLAY_MS,\n  className,\n}: FeatureAi01Props = {}) {\n  const items = capabilities.length > 0 ? capabilities : DEFAULT_CAPABILITIES;\n  const [index, setIndex] = useState(0);\n  const [hovered, setHovered] = useState<number | null>(null);\n\n  const restTimer = useRef<number | null>(null);\n  const clearRest = () => {\n    if (restTimer.current !== null) window.clearTimeout(restTimer.current);\n    restTimer.current = null;\n  };\n  const previewOnRest = (i: number) => {\n    clearRest();\n    restTimer.current = window.setTimeout(() => setHovered(i), 100);\n  };\n  useEffect(() => clearRest, []);\n\n  const [engaged, setEngaged] = useState(false);\n  const engage = () => setEngaged(true);\n\n  const sectionRef = useRef<HTMLElement>(null);\n  const inView = useInView(sectionRef, { amount: 0.35 });\n  const reducedMotion = useReducedMotion();\n  const autoplaying = !engaged && inView && !reducedMotion;\n\n  useEffect(() => {\n    if (!autoplaying) return;\n    const id = window.setInterval(\n      () => setIndex((i) => (i + 1) % items.length),\n      autoplayMs,\n    );\n    return () => window.clearInterval(id);\n  }, [autoplaying, items.length, autoplayMs]);\n\n  const safeIndex = index < items.length ? index : 0;\n  const shown =\n    hovered !== null && hovered < items.length ? hovered : safeIndex;\n  const current = items[shown];\n\n  return (\n    <MotionConfig reducedMotion=\"user\">\n      <section\n        ref={sectionRef}\n        className={cn(\n          \"relative overflow-x-clip bg-[#f1f1ef] py-16 text-neutral-900 lg:py-24\",\n          className,\n        )}\n      >\n        <div className=\"relative mx-auto max-w-7xl border-x border-neutral-900/[0.14]\">\n          <Separator className=\"absolute top-0 left-1/2 w-screen -translate-x-1/2 bg-neutral-900/[0.14]\" />\n          <Separator className=\"absolute bottom-0 left-1/2 w-screen -translate-x-1/2 bg-neutral-900/[0.14]\" />\n\n          <header className=\"grid items-center gap-8 border-b border-neutral-900/[0.08] px-6 py-10 sm:px-10 lg:grid-cols-[minmax(0,1.3fr)_minmax(0,0.7fr)] lg:gap-10 lg:py-10\">\n            <div>\n              <h2 className=\"text-[clamp(2rem,4.6vw,3.15rem)] leading-[1.04] font-normal tracking-[-0.035em] text-balance\">\n                Inference infrastructure that holds up in production.\n              </h2>\n              <p className=\"mt-4 max-w-xl text-[15px] leading-tight text-neutral-800\">\n                Serve open and custom models on dedicated GPUs without\n                assembling the stack yourself — scheduling, autoscaling,\n                caching, and observability arrive as one system, behind a single\n                API.\n              </p>\n\n              <div className=\"mt-7 flex flex-wrap items-center gap-3\">\n                <Button\n                  asChild\n                  className={cn(\n                    \"inline-flex items-center justify-center\",\n                    \"h-auto px-6 py-3.5\",\n                    \"text-[15px] font-medium text-white\",\n                    \"rounded-[6px]\",\n                    \"border-t border-r border-b border-l border-t-[#7E8675] border-r-[rgba(8,20,0,0.07)] border-b-[rgba(6,13,2,0.69)] border-l-[rgba(8,20,0,0.07)]\",\n                    \"bg-clip-border bg-transparent hover:bg-transparent bg-[linear-gradient(180deg,#7E8675_0%,rgba(61,69,53,0.87)_50%,#2F3927_100%)]\",\n                    \"shadow-[inset_1px_1px_5px_rgba(255,255,255,0.25),inset_-1px_-1px_5px_rgba(255,255,255,0.22)]\",\n                    \"active:not-aria-[haspopup]:translate-y-0 active:not-aria-[haspopup]:scale-100\",\n                    \"outline-none focus-visible:ring-2 focus-visible:ring-[#5f6b52]/45 focus-visible:ring-offset-2 focus-visible:ring-offset-[#f1f1ef] focus-visible:border-[rgba(8,20,0,0.07)] focus-visible:border-t-[#7E8675] focus-visible:border-b-[rgba(6,13,2,0.69)]\",\n                  )}\n                >\n                  <motion.a\n                    href=\"#\"\n                    whileTap={{ scale: 0.96 }}\n                    transition={{ type: \"spring\", duration: 0.3, bounce: 0 }}\n                  >\n                    Start building\n                  </motion.a>\n                </Button>\n\n                <Button\n                  asChild\n                  className={cn(\n                    \"inline-flex items-center justify-center\",\n                    \"h-auto px-6 py-3.5\",\n                    \"text-[15px] font-medium text-[#59654F]\",\n                    \"rounded-[6px] border-transparent\",\n                    \"bg-clip-border bg-transparent hover:bg-transparent bg-[linear-gradient(180deg,#FFFFFF_0%,rgba(10,14,5,0.13)_100%)]\",\n                    \"shadow-[inset_0_0_0_1px_rgba(131,127,126,0.09),1px_1px_0px_0px_rgba(4,0,0,0.12),-1px_1px_0px_0px_rgba(4,0,0,0.12)]\",\n                    \"active:not-aria-[haspopup]:translate-y-0 active:not-aria-[haspopup]:scale-100\",\n                    \"outline-none focus-visible:border-transparent focus-visible:ring-2 focus-visible:ring-[#5f6b52]/45 focus-visible:ring-offset-2 focus-visible:ring-offset-[#f1f1ef]\",\n                  )}\n                >\n                  <motion.a\n                    href=\"#\"\n                    whileTap={{ scale: 0.96 }}\n                    transition={{ type: \"spring\", duration: 0.3, bounce: 0 }}\n                  >\n                    Talk to an engineer\n                  </motion.a>\n                </Button>\n              </div>\n            </div>\n            <GpuInfrastructure className=\"mx-auto max-w-[420px] lg:-my-8\" />\n          </header>\n\n          <div className=\"grid lg:grid-cols-2 lg:divide-x lg:divide-neutral-900/[0.08]\">\n            <Accordion\n              type=\"multiple\"\n              defaultValue={[\"0\"]}\n              className=\"px-6 py-8 sm:px-10 lg:hidden\"\n            >\n              {items.map((c, i) => (\n                <AccordionItem\n                  key={c.word}\n                  value={String(i)}\n                  className=\"not-last:border-b not-last:border-neutral-900/[0.08]\"\n                >\n                  <AccordionTrigger\n                    className={cn(\n                      \"items-center gap-4 py-4 font-light text-[#6f6f6b] hover:no-underline\",\n                      \"text-[clamp(1.5rem,5.2vw,2rem)] leading-[1.32] tracking-[-0.02em]\",\n                      \"data-[state=open]:font-normal data-[state=open]:text-[#111111]\",\n                      \"focus-visible:border-transparent focus-visible:ring-2 focus-visible:ring-neutral-900/20\",\n                      \"**:data-[slot=accordion-trigger-icon]:size-5 **:data-[slot=accordion-trigger-icon]:self-center **:data-[slot=accordion-trigger-icon]:text-neutral-900/40\",\n                    )}\n                  >\n                    {c.word}.\n                  </AccordionTrigger>\n                  <AccordionContent className=\"max-w-[54ch] pb-5 text-[14px] leading-[1.55] text-neutral-700\">\n                    {c.copy}\n                  </AccordionContent>\n                </AccordionItem>\n              ))}\n            </Accordion>\n\n            <ul\n              className=\"hidden flex-col gap-1 px-6 py-12 sm:px-10 lg:flex lg:gap-2 lg:py-16\"\n              onMouseLeave={() => {\n                clearRest();\n                setHovered(null);\n              }}\n            >\n              {items.map((c, i) => (\n                <li key={c.word}>\n                  <Button\n                    variant=\"ghost\"\n                    onMouseEnter={() => {\n                      engage();\n                      previewOnRest(i);\n                    }}\n                    onFocus={() => {\n                      engage();\n                      setHovered(i);\n                    }}\n                    onClick={() => {\n                      engage();\n                      clearRest();\n                      setIndex(i);\n                    }}\n                    aria-current={i === safeIndex}\n                    className={cn(\n                      \"group -mx-3 flex h-auto w-full cursor-pointer items-center justify-start rounded-[12px] bg-none px-3 py-1 text-left shadow-none\",\n                      \"transition-colors duration-150 ease-out outline-none hover:bg-neutral-900/[0.035] hover:brightness-100\",\n                      \"focus-visible:border-transparent focus-visible:ring-2 focus-visible:ring-neutral-900/20\",\n                    )}\n                  >\n                    <Marker active={i === shown} />\n                    <motion.span\n                      animate={{\n                        color: i === shown ? \"#111111\" : \"#6f6f6b\",\n                        x: i === shown ? 2 : 0,\n                      }}\n                      transition={{ duration: 0.32, ease: EASE_OUT }}\n                      className={cn(\n                        \"text-[clamp(1.5rem,3.2vw,2.2rem)] leading-[1.32] tracking-[-0.02em]\",\n                        i === shown ? \"font-normal\" : \"font-light\",\n                      )}\n                    >\n                      {c.word}.\n                    </motion.span>\n                  </Button>\n                </li>\n              ))}\n            </ul>\n\n            <div className=\"hidden px-6 sm:px-10 lg:block lg:py-16\">\n              <Card\n                className={cn(\n                  \"relative flex aspect-[16/11] w-full flex-col justify-end gap-0 overflow-hidden rounded-[12px] border-0 bg-transparent p-6 text-inherit ring-0\",\n                  \"shadow-[inset_0_1px_0_rgba(255,255,255,0.18),inset_0_-1px_0_rgba(12,18,10,0.3),inset_0_0_0_1px_rgba(12,18,10,0.12)]\",\n                )}\n                style={{ backgroundImage: CARD_GRADIENT }}\n              >\n                <AnimatePresence initial={false}>\n                  <motion.div\n                    key={current.art.id}\n                    initial={{ opacity: 0, scale: 1.03 }}\n                    animate={{ opacity: 0.88, scale: 1 }}\n                    exit={{\n                      opacity: 0,\n                      transition: { duration: 0.22, ease: EASE_IN },\n                    }}\n                    transition={{\n                      opacity: {\n                        duration: 0.32,\n                        ease: EASE_OUT,\n                        delay: STAGGER.art,\n                      },\n                      scale: {\n                        duration: 0.56,\n                        ease: EASE_OUT,\n                        delay: STAGGER.art,\n                      },\n                    }}\n                    className=\"pointer-events-none absolute -top-[7%] -right-[6%] aspect-square w-[50%] [mask-image:radial-gradient(125%_125%_at_100%_0%,#000_58%,transparent_92%)] mix-blend-screen\"\n                  >\n                    <div className=\"h-full w-full [filter:invert(1)]\">\n                      <OpCanvas\n                        draw={current.art.draw}\n                        period={current.art.period}\n                        fps={current.art.fps}\n                        label={current.art.name}\n                      />\n                    </div>\n                  </motion.div>\n                </AnimatePresence>\n\n                <div\n                  className=\"pointer-events-none absolute inset-0 opacity-[0.16] mix-blend-overlay\"\n                  style={{\n                    backgroundImage: GRAIN,\n                    backgroundSize: \"320px 320px\",\n                  }}\n                />\n\n                <CardContent className=\"relative px-0\">\n                  <div className=\"flex items-baseline gap-3\">\n                    <div className=\"overflow-hidden\">\n                      <AnimatePresence mode=\"popLayout\" initial={false}>\n                        <motion.span\n                          key={shown}\n                          initial={{ y: \"100%\", opacity: 0 }}\n                          animate={{ y: 0, opacity: 1 }}\n                          exit={{\n                            y: \"-100%\",\n                            opacity: 0,\n                            transition: { duration: 0.2, ease: EASE_IN },\n                          }}\n                          transition={{\n                            y: { ...ROLL, delay: STAGGER.label },\n                            opacity: { duration: 0.22, delay: STAGGER.label },\n                          }}\n                          className=\"block text-[28px] leading-none font-normal tracking-tight text-[#eef1e7] tabular-nums\"\n                        >\n                          {String(shown + 1).padStart(2, \"0\")}\n                        </motion.span>\n                      </AnimatePresence>\n                    </div>\n                    <div className=\"overflow-hidden\">\n                      <AnimatePresence mode=\"popLayout\" initial={false}>\n                        <motion.span\n                          key={shown}\n                          initial={{ y: \"100%\", opacity: 0 }}\n                          animate={{ y: 0, opacity: 1 }}\n                          exit={{\n                            y: \"-100%\",\n                            opacity: 0,\n                            transition: { duration: 0.2, ease: EASE_IN },\n                          }}\n                          transition={{\n                            y: { ...ROLL, delay: STAGGER.label },\n                            opacity: { duration: 0.22, delay: STAGGER.label },\n                          }}\n                          className=\"block\"\n                        >\n                          <Badge\n                            variant=\"ghost\"\n                            className={cn(\n                              \"h-auto rounded-none border-0 bg-transparent px-0 py-0 font-mono text-[10px] font-normal tracking-[0.18em] text-[#eef1e7]/65 uppercase\",\n                              \"hover:bg-transparent hover:text-[#eef1e7]/65\",\n                            )}\n                          >\n                            {current.word}\n                          </Badge>\n                        </motion.span>\n                      </AnimatePresence>\n                    </div>\n                  </div>\n\n                  <AnimatePresence mode=\"wait\" initial={false}>\n                    <motion.p\n                      key={shown}\n                      initial={{ opacity: 0, y: 8 }}\n                      animate={{ opacity: 1, y: 0 }}\n                      exit={{\n                        opacity: 0,\n                        y: -6,\n                        transition: { duration: 0.2, ease: EASE_IN },\n                      }}\n                      transition={{\n                        duration: 0.3,\n                        ease: EASE_OUT,\n                        delay: STAGGER.copy,\n                      }}\n                      className=\"mt-3 max-w-[54ch] text-[13px] leading-[1.55] text-[#eef1e7]/75\"\n                    >\n                      {current.copy}\n                    </motion.p>\n                  </AnimatePresence>\n                </CardContent>\n              </Card>\n            </div>\n          </div>\n        </div>\n      </section>\n    </MotionConfig>\n  );\n}\n",
      "type": "registry:component",
      "target": "~/components/craftui/sections/feature-ai-01/default.tsx"
    }
  ],
  "meta": {
    "displayName": "Feature AI 01 - Feature AI 01",
    "description": "A split feature section for AI, GPU and developer-infrastructure marketing pages: an isometric compute-stack diagram anchors the header, a list of capability words sits on the left, and an olive card on the right answers each one with body copy and a generative canvas loop. The card walks itself through all six capabilities on autoplay so a scroller sees the whole story, then hands control over permanently the moment someone hovers, focuses or taps a row. Useful anywhere a platform has more claims than a hero can hold and each claim needs its own sentence without stacking six cards down the page.",
    "category": "feature-section",
    "tags": [
      "feature",
      "section",
      "ai",
      "infrastructure",
      "canvas",
      "generative",
      "isometric",
      "autoplay",
      "hover"
    ],
    "animationType": "hover"
  }
}