{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "knife-edge-rack-focus",
  "title": "Knife Edge Rack Focus",
  "description": "A card-scale loader substitute built on the Foucault knife-edge test: a knife edge racks through a mirror's focus, sweeping the aperture's shadow pattern from one side to a flat null and back, with four baked zonal errors crossing that null at their own moment.",
  "dependencies": [],
  "files": [
    {
      "path": "registry/core/knife-edge-rack-focus/component.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n// KnifeEdgeRackFocus — a card-scale loader substitute built on the Foucault\n// knife-edge test: a knife edge is racked (moved axially) through a mirror's\n// point of focus, and the shadow pattern cast back across the aperture\n// sweeps from one side to a flat uniform grey exactly at the null, then to\n// the other side. A local zone that departs from the ideal sphere crosses\n// that null at a slightly different knife position than its neighbours, so\n// it reads as a ring rising or sinking out of the otherwise-flat field —\n// which is the real diagnostic signal a real optician is looking for.\n//\n// RENDERING: rather than raster a 2D field, the whole pattern collapses to\n// ONE function of radius, L(r, t) = clamp(0.5 + K*(t - offset(r)), 0, 1),\n// because each of the 4 baked zonal errors is a concentric shell and every\n// point at the same radius shares the same optical path. offset(r) is a\n// piecewise-linear interpolation between 4 anchor offsets at r = 0.25, 0.5,\n// 0.7, 0.9 (of disc radius), spaced 0.12 apart, extrapolated flat beyond the\n// anchors. That single 1D function is sampled at 48 points and painted as\n// one radial CanvasGradient per frame — cheap, and the smoothness of a real\n// shadow front comes for free from the gradient interpolation instead of a\n// pixel raster.\n//\n// THE RACK is a triangle wave in knife position t, [-1, 1], 8s out + 8s\n// back (16s full period) — never a reset, a real tester racks back and\n// forth to bracket the null repeatedly. Exactly at a null (|t| < 0.05) the\n// drive itself PAUSES for ~0.6s before continuing, mirroring how a real\n// tester dwells there; that pause, not the sweep, is the clearest single\n// followable event.\n//\n// Colours: the shadow ramp spans --foreground (dark) to --background\n// (light) directly — this is a literal light/shadow phenomenon in both\n// themes, so the mapping never inverts, only the read stays a shadow.\n// --border is never used as a fill/stroke (it is a separator token only).\n\nconst RACK_PERIOD_S = 16; // 8s out + 8s back\nconst NULL_WINDOW = 0.05; // |t| under this counts as \"at the null\"\nconst NULL_DWELL_S = 0.6;\nconst SHADOW_K = 1.8;\nconst ZONE_ANCHORS = [0.25, 0.5, 0.7, 0.9];\nconst ZONE_OFFSETS = [-0.18, -0.06, 0.06, 0.18]; // spaced 0.12 apart\nconst RADIUS_RATIO = 0.42; // disc radius = 0.42 * min(w, h)\nconst GRADIENT_STEPS = 48;\nconst GRADIENT_REACH = 1.05; // sample slightly past the rim for a soft edge\n\n// reduced-motion freeze frame: t = 0.3, named \"half-sweep-zoned\" — clear\n// rise/fall banding across all 4 zones is visible here, unlike the null\n// itself (t = 0) which is nearly featureless and would under-inform a\n// static viewer. Deliberately not t0/the null.\nconst FREEZE_LABEL = \"half-sweep-zoned\";\nconst FREEZE_T = 0.3;\n\ntype RGB = [number, number, number];\n\nfunction parseHex(raw: string): RGB | null {\n  const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(raw.trim());\n  if (!m) return null;\n  let h = m[1];\n  if (h.length === 3) h = h.split(\"\").map((c) => c + c).join(\"\");\n  const n = parseInt(h, 16);\n  return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nfunction mixRGB(a: RGB, b: RGB, t: number): RGB {\n  const c = Math.max(0, Math.min(1, t));\n  return [\n    Math.round(a[0] + (b[0] - a[0]) * c),\n    Math.round(a[1] + (b[1] - a[1]) * c),\n    Math.round(a[2] + (b[2] - a[2]) * c),\n  ];\n}\n\nfunction rgbToCss([r, g, b]: RGB): string {\n  return `rgb(${r},${g},${b})`;\n}\n\n// offset(r): piecewise-linear through the 4 anchors, flat-clamped outside\nfunction zoneOffsetAt(rFrac: number): number {\n  if (rFrac <= ZONE_ANCHORS[0]!) return ZONE_OFFSETS[0]!;\n  if (rFrac >= ZONE_ANCHORS[ZONE_ANCHORS.length - 1]!) {\n    return ZONE_OFFSETS[ZONE_OFFSETS.length - 1]!;\n  }\n  for (let i = 0; i < ZONE_ANCHORS.length - 1; i++) {\n    const a0 = ZONE_ANCHORS[i]!;\n    const a1 = ZONE_ANCHORS[i + 1]!;\n    if (rFrac >= a0 && rFrac <= a1) {\n      const f = (rFrac - a0) / (a1 - a0);\n      return ZONE_OFFSETS[i]! + (ZONE_OFFSETS[i + 1]! - ZONE_OFFSETS[i]!) * f;\n    }\n  }\n  return 0;\n}\n\nfunction shadowL(rFrac: number, t: number): number {\n  return Math.max(0, Math.min(1, 0.5 + SHADOW_K * (t - zoneOffsetAt(rFrac))));\n}\n\n// triangle wave over RACK_PERIOD_S, driveTime -> t in [-1, 1]\nfunction triangleT(driveTime: number): number {\n  const ph = ((driveTime / RACK_PERIOD_S) % 1 + 1) % 1;\n  return ph < 0.5 ? -1 + 4 * ph : 1 - 4 * (ph - 0.5);\n}\n\n// nearest null (t = 0) as a driveTime value, mod RACK_PERIOD_S: nulls occur\n// at ph = 0.25 and ph = 0.75\nfunction nearestNullDriveTime(driveTime: number): number {\n  const period = RACK_PERIOD_S;\n  const ph = ((driveTime / period) % 1 + 1) % 1;\n  const candidates = [0.25, 0.75];\n  let best = candidates[0]!;\n  let bestDist = Infinity;\n  for (const c of candidates) {\n    const d = Math.min(Math.abs(ph - c), 1 - Math.abs(ph - c));\n    if (d < bestDist) {\n      bestDist = d;\n      best = c;\n    }\n  }\n  const base = Math.floor(driveTime / period) * period;\n  return base + best * period;\n}\n\nexport interface KnifeEdgeRackFocusProps {\n  /** accessible status text announced to assistive tech */\n  label?: string;\n  /** extra classes merged onto the rendered root element */\n  className?: string;\n}\n\nexport function KnifeEdgeRackFocus({\n  label = \"Testing\",\n  className = \"\",\n}: KnifeEdgeRackFocusProps) {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n\n  useEffect(() => {\n    const container = containerRef.current;\n    const canvas = canvasRef.current;\n    if (!container || !canvas) return;\n    const ctx = canvas.getContext(\"2d\");\n    if (!ctx) return;\n\n    const reduced = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n    let disposed = false;\n    let visible = true;\n    let raf = 0;\n\n    let w = 0;\n    let h = 0;\n    let dpr = 1;\n    let radius = 0;\n\n    let fg: RGB = [23, 23, 23];\n    let bg: RGB = [255, 255, 255];\n\n    // no paint before this first read\n    const deriveColors = () => {\n      const cs = getComputedStyle(document.documentElement);\n      fg = parseHex(cs.getPropertyValue(\"--foreground\")) ?? fg;\n      bg = parseHex(cs.getPropertyValue(\"--background\")) ?? bg;\n    };\n\n    const build = () => {\n      const rect = container.getBoundingClientRect();\n      w = Math.round(rect.width);\n      h = Math.round(rect.height);\n      if (w < 2 || h < 2) return;\n      dpr = Math.min(2, window.devicePixelRatio || 1);\n      canvas.width = w * dpr;\n      canvas.height = h * dpr;\n      radius = RADIUS_RATIO * Math.min(w, h);\n    };\n\n    // the shadow pattern is one function of radius, painted as a single\n    // radial gradient — the smoothness of a real shadow front comes free\n    // from gradient interpolation rather than a pixel raster\n    const drawDisc = (t: number, showPausedRing: boolean) => {\n      if (w < 2 || h < 2 || radius <= 0) return;\n      const cx = w / 2;\n      const cy = h / 2;\n      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n      ctx.clearRect(0, 0, w, h);\n\n      const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius * GRADIENT_REACH);\n      for (let i = 0; i <= GRADIENT_STEPS; i++) {\n        const stop = i / GRADIENT_STEPS;\n        const rFrac = stop / GRADIENT_REACH;\n        const L = shadowL(Math.min(1, rFrac), t);\n        grad.addColorStop(stop, rgbToCss(mixRGB(fg, bg, L)));\n      }\n\n      ctx.save();\n      ctx.beginPath();\n      ctx.arc(cx, cy, radius, 0, Math.PI * 2);\n      ctx.closePath();\n      ctx.fillStyle = grad;\n      ctx.fill();\n\n      // a manual \"hold\" affordance while the user is pausing the rack at a\n      // null — foreground only, never --border as a stroke and never accent\n      if (showPausedRing) {\n        ctx.lineWidth = 1.5;\n        ctx.strokeStyle = `rgba(${fg[0]},${fg[1]},${fg[2]},0.4)`;\n        ctx.stroke();\n      }\n      ctx.restore();\n    };\n\n    const drawReduced = () => {\n      drawDisc(FREEZE_T, false);\n    };\n\n    let driveTime = 0;\n    let dwelling = false;\n    let dwellElapsed = 0;\n    let userPaused = false;\n    let pausedDriveTime = 0;\n    let last = 0;\n\n    const loop = (now: number) => {\n      if (disposed || !visible) {\n        raf = 0;\n        return;\n      }\n      const dt = last === 0 ? 1 / 60 : Math.min(0.05, (now - last) / 1000);\n      last = now;\n\n      let t: number;\n      if (userPaused) {\n        t = triangleT(pausedDriveTime);\n      } else if (dwelling) {\n        dwellElapsed += dt;\n        t = triangleT(driveTime);\n        if (dwellElapsed >= NULL_DWELL_S) {\n          dwelling = false;\n          dwellElapsed = 0;\n        }\n      } else {\n        driveTime += dt;\n        t = triangleT(driveTime);\n        if (Math.abs(t) < NULL_WINDOW) {\n          dwelling = true;\n          dwellElapsed = 0;\n        }\n      }\n\n      drawDisc(t, userPaused);\n      raf = requestAnimationFrame(loop);\n    };\n\n    const startLoop = () => {\n      if (!raf && !reduced) {\n        last = 0;\n        raf = requestAnimationFrame(loop);\n      }\n    };\n\n    // press pauses the rack at the nearest null and holds it there; release\n    // resumes the sweep from where it paused. Never alters the baked zone\n    // profile, never touches SHADOW_K or the offsets.\n    const onPointerDown = () => {\n      pausedDriveTime = nearestNullDriveTime(driveTime);\n      userPaused = true;\n      drawDisc(triangleT(pausedDriveTime), true);\n    };\n    const endPause = () => {\n      if (!userPaused) return;\n      userPaused = false;\n      driveTime = pausedDriveTime;\n      dwelling = false;\n      dwellElapsed = 0;\n    };\n\n    deriveColors();\n    build();\n    if (reduced) {\n      drawReduced();\n    } else {\n      startLoop();\n    }\n\n    const ro = new ResizeObserver(() => {\n      build();\n      if (reduced) drawReduced();\n    });\n    ro.observe(container);\n\n    const mo = new MutationObserver(() => {\n      deriveColors();\n      if (reduced) {\n        drawReduced();\n      } else if (userPaused) {\n        drawDisc(triangleT(pausedDriveTime), true);\n      }\n    });\n    mo.observe(document.documentElement, {\n      attributes: true,\n      attributeFilter: [\"class\"],\n    });\n\n    const io = new IntersectionObserver((entries) => {\n      visible = entries[0]?.isIntersecting ?? true;\n      if (visible && !reduced) startLoop();\n    });\n    io.observe(container);\n\n    if (!reduced) {\n      container.addEventListener(\"pointerdown\", onPointerDown);\n      container.addEventListener(\"pointerup\", endPause);\n      container.addEventListener(\"pointercancel\", endPause);\n      container.addEventListener(\"pointerleave\", endPause);\n    }\n\n    return () => {\n      disposed = true;\n      cancelAnimationFrame(raf);\n      raf = 0;\n      ro.disconnect();\n      mo.disconnect();\n      io.disconnect();\n      container.removeEventListener(\"pointerdown\", onPointerDown);\n      container.removeEventListener(\"pointerup\", endPause);\n      container.removeEventListener(\"pointercancel\", endPause);\n      container.removeEventListener(\"pointerleave\", endPause);\n    };\n  }, []);\n\n  return (\n    <div\n      ref={containerRef}\n      role=\"status\"\n      className={`relative aspect-square w-full max-w-[280px] touch-none overflow-hidden rounded-md border border-border bg-background ${className}`}\n    >\n      <span className=\"sr-only\">{label}</span>\n      <canvas ref={canvasRef} aria-hidden=\"true\" className=\"absolute inset-0 h-full w-full\" />\n    </div>\n  );\n}\n\nexport { FREEZE_LABEL };\n",
      "type": "registry:ui",
      "target": "components/ui/knife-edge-rack-focus.tsx"
    }
  ],
  "meta": {
    "collection": "core",
    "tags": [
      "canvas",
      "loader",
      "activity-indicator",
      "optics",
      "foucault-test",
      "shadow-pattern",
      "generative",
      "physics"
    ],
    "instruction": "Build <KnifeEdgeRackFocus label? className?> as a self-contained Canvas 2D loader, DPR-clamped to 2, direct-DOM rAF as the sole writer, zero dependencies. Disc radius = 0.42 * min(container width, height). The shadow pattern collapses to ONE function of radius, L(r, t) = clamp(0.5 + 1.8 * (t - offset(r)), 0, 1), because every point at a given radius shares the same optical path in a real Foucault test — no 2D raster needed. offset(r) is a piecewise-linear interpolation between 4 anchor offsets [-0.18, -0.06, 0.06, 0.18] (spaced 0.12 apart) at radii [0.25, 0.5, 0.7, 0.9] of the disc radius, flat-clamped beyond the anchors. Painted every frame as ONE radial CanvasGradient sampled at 48 stops from r=0 to 1.05*radius (the extra 5% for a soft edge) — the smoothness of a real shadow front comes from gradient interpolation, not per-pixel work, so cost stays flat regardless of how far the disc grows. t is driven by a triangle wave over a 16s period (8s rising -1->1, 8s falling 1->-1) accumulated from an internal driveTime that only advances while not paused/dwelling (never derived from absolute elapsed time). Exactly at a null (|t| < 0.05) the drive PAUSES for 0.6s before continuing — that dwell, not the sweep itself, is the clearest single followable event, mirroring how a real tester holds position there. The 4 zone offsets crossing t=0 at different points in the sweep is what makes concentric rings visibly rise or sink relative to their neighbours rather than the whole disc changing uniformly — the real diagnostic signal. Pointer interaction: pointerdown snaps the drive to the nearest null (by driveTime modulo the 16s period, comparing against the two null phases at ph=0.25 and ph=0.75) and holds it there via a separate userPaused flag (driveTime itself frozen, never advanced) until pointerup/pointercancel/pointerleave, which resumes the sweep exactly where it paused; a paused-state affordance is a 1.5px stroke around the disc rim at foreground/40% alpha (never --ns-accent, never --border as a stroke). Colours: the fill is a direct two-point mix between --foreground (L=0) and --background (L=1) via a canvas fillStyle probe reading getComputedStyle(document.documentElement) before first paint and re-derived on a documentElement class MutationObserver — this ramp never inverts between themes because it is a literal light/shadow phenomenon, not a decorative palette. A ResizeObserver rebuilds geometry on layout change; an IntersectionObserver pauses/resumes the rAF loop off-screen. Under prefers-reduced-motion the component renders one static frame at t = 0.3, named FREEZE_LABEL = 'half-sweep-zoned' (clear rise/fall banding across all 4 zones, deliberately not the null itself, which is nearly featureless and would under-inform a static viewer) — the loop, pointer listeners and IntersectionObserver are never attached, though the ResizeObserver and MutationObserver stay live. Accessibility: the root carries role=\"status\" with a visually-hidden label (default 'Testing'); the canvas is aria-hidden. Props: label (status text, default 'Testing'), className (merged onto the root)."
  },
  "type": "registry:ui"
}