{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "light-trail-write",
  "title": "Light Trail Write",
  "description": "A point of light writes the Remocn wordmark path with a cooling trail.",
  "dependencies": ["remotion", "@remotion/paths"],
  "files": [
    {
      "path": "registry/remocn/light-trail-write/index.tsx",
      "content": "\"use client\";\n\nimport {\n  getBoundingBox,\n  getLength,\n  getPointAtLength,\n  warpPath,\n} from \"@remotion/paths\";\nimport { useId, useMemo } from \"react\";\nimport {\n  AbsoluteFill,\n  Easing,\n  interpolate,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\n\n/**\n * Beat sheet (30fps, speed 1):\n * 0–10     a point of light ignites at the start of the stroke.\n * 6–86     it writes the path; the trail cools from hot white through the\n *          silk palette (peach, violet, indigo) to nothing over ~20 frames,\n *          with a faint exposure memory behind it.\n * 86–98    the head burns out and the whole exposure flashes in at once.\n * 98–122   a slanted bar of the same light sweeps across: behind it the\n *          script is gone and the real remocn logo stands in its place.\n * 122–160  the logo holds, a silk sheen drifting slowly through it.\n */\n\nexport interface LightTrailWriteProps {\n  /**\n   * A single monoline SVG path (any coordinate space) to paint. Defaults to a\n   * slanted script \"remocn\". Draw it in writing order: the light follows `d`.\n   */\n  path?: string;\n  /** Stroke width in path units; defaults to 3.4% of the path height. */\n  strokeWidth?: number;\n  /**\n   * The logo the script turns into: \"solid\" is lit white with a silk sheen,\n   * \"accent\" is lit in the accent.\n   */\n  finish?: \"solid\" | \"accent\";\n  accent?: string;\n  /** Playback multiplier. */\n  speed?: number;\n}\n\n/** Monoline script \"remocn\", baseline y=0, x-height 100, written upright. */\nconst SCRIPT_UPRIGHT = [\n  \"M -34 8\",\n  \"C -12 6 18 -40 32 -96\",\n  \"C 36 -84 44 -78 56 -82\",\n  \"C 64 -85 70 -92 78 -92\",\n  \"C 74 -60 70 -24 72 -2\",\n  \"C 74 6 88 4 98 -12\",\n  \"C 112 -32 140 -52 140 -76\",\n  \"C 140 -96 116 -98 108 -80\",\n  \"C 98 -56 104 -4 132 -2\",\n  \"C 150 -1 162 -14 172 -30\",\n  \"C 178 -48 182 -80 186 -96\",\n  \"C 188 -64 186 -30 186 0\",\n  \"C 188 -48 200 -96 218 -96\",\n  \"C 234 -96 238 -82 238 -62\",\n  \"C 238 -40 236 -18 236 0\",\n  \"C 238 -48 250 -96 268 -96\",\n  \"C 284 -96 288 -82 288 -62\",\n  \"C 288 -36 286 -14 294 -4\",\n  \"C 302 4 316 0 326 -24\",\n  \"C 334 -48 344 -88 362 -98\",\n  \"C 346 -98 338 -74 338 -50\",\n  \"C 338 -22 348 -2 362 -2\",\n  \"C 378 -2 386 -24 386 -50\",\n  \"C 386 -78 376 -98 362 -98\",\n  \"C 374 -96 392 -88 412 -88\",\n  \"C 418 -96 430 -100 437 -92\",\n  \"C 428 -100 413 -88 413 -60\",\n  \"C 413 -26 421 -2 438 -2\",\n  \"C 454 -2 464 -14 472 -28\",\n  \"C 476 -50 480 -84 484 -96\",\n  \"C 486 -64 484 -30 484 0\",\n  \"C 486 -48 498 -96 516 -96\",\n  \"C 532 -96 536 -82 536 -62\",\n  \"C 536 -36 534 -14 542 -4\",\n  \"C 552 6 572 2 594 -18\",\n].join(\" \");\n\nconst SLANT = Math.tan((13 * Math.PI) / 180);\nconst DEFAULT_PATH = warpPath(SCRIPT_UPRIGHT, ({ x, y }) => ({\n  x: x - y * SLANT,\n  y,\n}));\n\nconst BG = \"#050508\";\nconst HOT = [255, 255, 255];\n\n/**\n * gradients.sh \"silk\" palette: [#3b3fd8, #f3d6c0, #8a7bff]. The light cools\n * through it as it trails, and it is the sheen inside the finished logo.\n */\nconst SILK = [\"#3b3fd8\", \"#f3d6c0\", \"#8a7bff\"] as const;\n/** The cooling ramp of the trail, by age: hot → peach → violet → indigo. */\nconst COOL = [HOT, rgb(SILK[1]), rgb(SILK[2]), rgb(SILK[0])];\nconst WRITE_START = 6;\nconst WRITE_END = 86;\nconst TRAIL = 20;\nconst STEPS = 2;\n\nconst CLAMP = {\n  extrapolateLeft: \"clamp\",\n  extrapolateRight: \"clamp\",\n} as const;\nconst EASE_WRITE = Easing.bezier(0.42, 0, 0.58, 1);\nconst EASE_OUT = Easing.bezier(0.22, 1, 0.36, 1);\nconst EASE_IO = Easing.bezier(0.65, 0, 0.35, 1);\nconst SWEEP_START = WRITE_END + 12;\nconst SWEEP_END = SWEEP_START + 24;\n\nfunction rgb(hex: string) {\n  const h = hex.replace(\"#\", \"\");\n  const n =\n    h.length === 3\n      ? h\n          .split(\"\")\n          .map((c) => c + c)\n          .join(\"\")\n      : h.slice(0, 6);\n  return [0, 2, 4].map((i) => Number.parseInt(n.slice(i, i + 2), 16));\n}\n\nfunction mixRgb(a: number[], b: number[], k: number) {\n  return a.map((v, i) => Math.round(v + (b[i] - v) * k));\n}\n\n/** Color of the trail `age` frames behind the head: white → silk → gone. */\nfunction trailColor(age: number) {\n  const k = interpolate(age, [0.5, 4, 9, 16], [0, 1, 2, 3], CLAMP);\n  const i = Math.min(2, Math.floor(k));\n  const c = mixRgb(COOL[i], COOL[i + 1], k - i);\n  const alpha = interpolate(age, [0, 6, TRAIL], [1, 0.85, 0], {\n    ...CLAMP,\n    easing: Easing.bezier(0.3, 0, 0.6, 1),\n  });\n  return { color: `rgb(${c[0]},${c[1]},${c[2]})`, alpha };\n}\n\n/**\n * The remocn.dev logo as outlines: the R mark (0.76em, on the baseline) and\n * \"emocn\" in Manrope 600 at -0.025em, 100 units per em, baseline at y = 0.\n * Glyph contours overlap (m, n, the e's bar), so they fill nonzero.\n */\nconst LOGO_R =\n  \"M 0.01 -75.54 C 0.01 -75.02 0.2 -74.42 0.62 -73.66 C 2.78 -69.75 7.61 -66.29 12.28 -65.3 C 12.99 -65.15 13.12 -65.15 29.09 -65.09 C 43.06 -65.04 45.3 -65.02 46.03 -64.92 C 50.88 -64.29 54.46 -62.03 56.26 -58.45 C 58.41 -54.17 58.04 -47.64 55.42 -43.69 C 53.58 -40.93 50.76 -39.21 47.13 -38.64 C 46.88 -38.6 39.73 -38.17 31.25 -37.68 C 14.05 -36.7 15.3 -36.81 13.69 -36.15 C 11.26 -35.16 8.4 -33.15 6.03 -30.78 C 2.75 -27.5 0.74 -23.97 0.14 -20.45 C 0.07 -20.04 0.05 -17.62 0.02 -9.96 L 0 0 5.38 0 L 10.76 0 10.78 -8.41 C 10.81 -17.54 10.8 -17.23 11.22 -18.8 C 12.33 -22.99 15.77 -25.76 20.63 -26.4 C 21.07 -26.45 22.31 -26.47 24.66 -26.45 C 28.37 -26.42 28.73 -26.38 30.13 -25.93 C 32.04 -25.3 33.78 -24 35.11 -22.18 C 35.39 -21.79 39.26 -17.21 43.7 -11.99 C 48.14 -6.78 51.87 -2.39 51.99 -2.23 C 52.12 -2.08 52.36 -1.65 52.54 -1.3 C 52.94 -0.52 53.27 -0.19 53.81 -0.07 C 54.06 -0.02 56.02 0 60.21 -0.02 L 66.24 -0.04 57.07 -11.99 C 52.03 -18.57 47.84 -24.05 47.77 -24.17 C 47.19 -25.12 47.36 -26.45 48.17 -27.32 C 48.56 -27.74 48.89 -27.92 49.85 -28.24 C 54.44 -29.74 58.96 -32.63 62.25 -36.17 C 68.26 -42.64 70.23 -50.91 67.61 -58.77 C 64.87 -67.05 57.7 -73.72 49.61 -75.53 C 47.51 -75.99 49.86 -75.95 23.69 -75.98 L 0.01 -76 0.01 -75.54 Z\";\n\nconst LOGO_EMOCN = [\n  // e\n  \"M105.2 1.5L105.2 1.5Q97.1 1.5 91 -2Q85 -5.6 81.6 -11.9Q78.2 -18.2 78.2 -26.6L78.2 -26.6Q78.2 -35.4 81.5 -41.9Q84.9 -48.4 90.8 -52Q96.8 -55.5 104.7 -55.5L104.7 -55.5Q112.9 -55.5 118.7 -51.7Q124.5 -47.9 127.4 -40.8Q130.3 -33.8 129.7 -24.1L129.7 -24.1L119.2 -24.1L119.2 -27.9Q119.1 -37.3 115.6 -41.8Q112.2 -46.3 105.1 -46.3L105.1 -46.3Q97.2 -46.3 93.3 -41.3Q89.3 -36.4 89.3 -27L89.3 -27Q89.3 -18.1 93.3 -13.2Q97.2 -8.3 104.7 -8.3L104.7 -8.3Q109.6 -8.3 113.1 -10.6Q116.7 -12.8 118.7 -16.9L118.7 -16.9L128.9 -13.7Q125.8 -6.5 119.4 -2.5Q113 1.5 105.2 1.5ZM124.5 -24.1L85.9 -24.1L85.9 -32.2L124.5 -32.2L124.5 -24.1Z\",\n  // m\n  \"M212 0L201.6 0L201.6 -33.6Q201.6 -39.5 198.6 -42.8Q195.6 -46.1 190.7 -46.1L190.7 -46.1Q187.7 -46.1 185.2 -44.7Q182.8 -43.3 181.2 -40.6Q179.7 -37.9 179.7 -33.8L179.7 -33.8L174.7 -36.3Q174.6 -42 177.1 -46.3Q179.6 -50.6 183.9 -53Q188.3 -55.4 193.7 -55.4L193.7 -55.4Q202.4 -55.4 207.3 -50.1Q212.1 -44.9 212.1 -36.1L212.1 -36.1L212 0ZM147.3 0L136.8 0L136.8 -54L146.1 -54L146.1 -38.4L147.3 -38.4L147.3 0ZM179.7 0L169.2 0L169.3 -33.5Q169.3 -39.4 166.3 -42.7Q163.3 -46.1 158.3 -46.1L158.3 -46.1Q153.3 -46.1 150.3 -42.7Q147.3 -39.3 147.3 -33.8L147.3 -33.8L142.3 -37Q142.3 -42.3 144.8 -46.4Q147.4 -50.6 151.8 -53Q156.1 -55.4 161.6 -55.4L161.6 -55.4Q167.3 -55.4 171.4 -52.9Q175.4 -50.5 177.6 -46.2Q179.7 -41.8 179.7 -36.1L179.7 -36.1L179.7 0Z\",\n  // o\n  \"M245.3 1.5L245.3 1.5Q237.2 1.5 231.3 -2.1Q225.3 -5.8 222.1 -12.2Q218.9 -18.7 218.9 -27.1L218.9 -27.1Q218.9 -35.5 222.2 -41.9Q225.5 -48.4 231.4 -51.9Q237.4 -55.5 245.3 -55.5L245.3 -55.5Q253.4 -55.5 259.4 -51.9Q265.3 -48.2 268.6 -41.8Q271.8 -35.4 271.8 -27.1L271.8 -27.1Q271.8 -18.6 268.6 -12.2Q265.3 -5.8 259.3 -2.1Q253.4 1.5 245.3 1.5ZM245.3 -8.3L245.3 -8.3Q253.1 -8.3 256.9 -13.6Q260.8 -18.8 260.8 -27.1L260.8 -27.1Q260.8 -35.5 256.9 -40.6Q253 -45.7 245.3 -45.7L245.3 -45.7Q240.1 -45.7 236.7 -43.3Q233.3 -40.9 231.6 -36.7Q230 -32.6 230 -27.1L230 -27.1Q230 -18.6 233.9 -13.5Q237.8 -8.3 245.3 -8.3Z\",\n  // c\n  \"M303.4 1.5L303.4 1.5Q295.1 1.5 289.3 -2.2Q283.5 -5.9 280.5 -12.4Q277.4 -18.8 277.3 -27L277.3 -27Q277.4 -35.4 280.5 -41.8Q283.7 -48.2 289.5 -51.9Q295.4 -55.5 303.6 -55.5L303.6 -55.5Q312.4 -55.5 318.7 -51.1Q325 -46.7 327 -39.1L327 -39.1L316.6 -36.1Q315 -40.6 311.5 -43.1Q308 -45.7 303.4 -45.7L303.4 -45.7Q298.3 -45.7 295 -43.2Q291.7 -40.8 290.1 -36.6Q288.5 -32.4 288.4 -27L288.4 -27Q288.5 -18.7 292.3 -13.5Q296 -8.3 303.4 -8.3L303.4 -8.3Q308.5 -8.3 311.6 -10.7Q314.8 -13 316.4 -17.4L316.4 -17.4L327 -14.9Q324.3 -7 318.3 -2.7Q312.1 1.5 303.4 1.5Z\",\n  // n\n  \"M383.2 0L372.6 0L372.6 -26.6Q372.6 -29.7 372.1 -33Q371.6 -36.4 370.1 -39.2Q368.6 -42.1 365.9 -43.8Q363.3 -45.6 358.9 -45.6L358.9 -45.6Q356.1 -45.6 353.6 -44.6Q351.1 -43.7 349.3 -41.7Q347.4 -39.6 346.3 -36.3Q345.3 -32.9 345.3 -28.1L345.3 -28.1L338.8 -30.6Q338.8 -37.9 341.5 -43.5Q344.3 -49.2 349.4 -52.3Q354.6 -55.5 361.8 -55.5L361.8 -55.5Q367.4 -55.5 371.3 -53.7Q375.1 -51.9 377.4 -48.9Q379.8 -46 381.1 -42.6Q382.3 -39.1 382.8 -35.8Q383.2 -32.5 383.2 -30L383.2 -30L383.2 0ZM345.3 0L334.6 0L334.6 -54L344 -54L344 -38.4L345.3 -38.4L345.3 0Z\",\n];\n/** Ink box of the outlined logo, in its own units; the R is `rW` wide. */\nconst LOGO = { x: 0, y: -76, w: 383.2, h: 77.5, rW: 70.23 } as const;\n\n/** The whole logo in one fill (a colour or a `url(#gradient)`). */\nfunction LogoPaths({ fill }: { fill: string }) {\n  return (\n    <g fill={fill}>\n      <path d={LOGO_R} />\n      {LOGO_EMOCN.map((d) => (\n        <path key={d.slice(0, 16)} d={d} />\n      ))}\n    </g>\n  );\n}\n\nfunction Grain({ opacity }: { opacity: number }) {\n  const id = `g${useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n  return (\n    <svg\n      width=\"100%\"\n      height=\"100%\"\n      style={{ position: \"absolute\", inset: 0, opacity, pointerEvents: \"none\" }}\n      aria-hidden\n    >\n      <filter id={id}>\n        <feTurbulence\n          type=\"fractalNoise\"\n          baseFrequency=\"0.9\"\n          numOctaves={2}\n          seed={23}\n          stitchTiles=\"stitch\"\n        />\n        <feColorMatrix values=\"0 0 0 0 0.5  0 0 0 0 0.5  0 0 0 0 0.5  0 0 0 0.9 0\" />\n      </filter>\n      <rect width=\"100%\" height=\"100%\" filter={`url(#${id})`} />\n    </svg>\n  );\n}\n\nexport function LightTrailWrite({\n  path = DEFAULT_PATH,\n  strokeWidth,\n  finish = \"solid\",\n  accent = \"#3B5BFD\",\n  speed = 1,\n}: LightTrailWriteProps) {\n  const t = useCurrentFrame() * speed;\n  const { width, height } = useVideoConfig();\n  const uid = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n  const ids = {\n    wide: `w${uid}`,\n    mid: `m${uid}`,\n    head: `h${uid}`,\n    wash: `s${uid}`,\n    logo: `l${uid}`,\n    bloom: `b${uid}`,\n  };\n\n  const { len, box } = useMemo(\n    () => ({ len: getLength(path), box: getBoundingBox(path) }),\n    [path],\n  );\n  const bw = box.x2 - box.x1;\n  const bh = box.y2 - box.y1;\n  const sw = strokeWidth ?? bh * 0.034;\n\n  // fit the path to ~64% of the frame width (or 34% of the height)\n  const k = Math.min((width * 0.64) / bw, (height * 0.34) / bh);\n  const vbW = width / k;\n  const vbH = height / k;\n  const vbX = (box.x1 + box.x2) / 2 - vbW / 2;\n  const vbY = (box.y1 + box.y2) / 2 - vbH / 2 - vbH * 0.02;\n\n  const writeAt = (frame: number) =>\n    interpolate(frame, [WRITE_START, WRITE_END], [0, len], {\n      ...CLAMP,\n      easing: EASE_WRITE,\n    });\n  const headS = writeAt(t);\n  const head = getPointAtLength(path, Math.min(len - 0.01, headS)) ?? {\n    x: 0,\n    y: 0,\n  };\n\n  // light levels\n  const ignite = interpolate(t, [0, 10], [0, 1], {\n    ...CLAMP,\n    easing: EASE_OUT,\n  });\n  const burnOut = interpolate(\n    t,\n    [WRITE_END - 2, WRITE_END + 10],\n    [1, 0],\n    CLAMP,\n  );\n  const headOn = ignite * burnOut;\n  const memory = interpolate(t, [WRITE_START, WRITE_END], [0.06, 0.11], CLAMP);\n  const reveal = interpolate(t, [WRITE_END, WRITE_END + 10], [0, 1], {\n    ...CLAMP,\n    easing: EASE_OUT,\n  });\n  const drain = interpolate(t, [WRITE_END + 10, SWEEP_END], [0, 1], {\n    ...CLAMP,\n    easing: EASE_IO,\n  });\n  const glow = reveal * (1 - 0.7 * drain);\n\n  // the hand-over: a slanted bar of light crosses the frame; left of it the\n  // logo, right of it what is left of the script\n  const sweep = interpolate(t, [SWEEP_START, SWEEP_END], [0, 1], {\n    ...CLAMP,\n    easing: EASE_IO,\n  });\n  const sweeping = t >= SWEEP_START - 1 && t <= SWEEP_END + 1;\n  const logoW = width * 0.52;\n  const logoK = logoW / LOGO.w;\n  const logoH = LOGO.h * logoK;\n  const logoLeft = (width - logoW) / 2;\n  const logoTop = height * 0.5 - logoH / 2;\n  const edgeFrom = logoLeft - width * 0.12;\n  const edgeTo = logoLeft + logoW + width * 0.12;\n  const edge = edgeFrom + (edgeTo - edgeFrom) * sweep;\n  const slant = 103;\n  // where `edge` (on the centre row) falls along the slanted gradient line\n  const sn = Math.sin((slant * Math.PI) / 180);\n  const gradLen =\n    width * sn + height * Math.abs(Math.cos((slant * Math.PI) / 180));\n  const edgePct = 50 + (((edge - width / 2) * sn) / gradLen) * 100;\n  const soft = 3.5;\n  const logoMask =\n    t >= SWEEP_END\n      ? undefined\n      : `linear-gradient(${slant}deg, #000 ${edgePct - soft}%, transparent ${edgePct + soft}%)`;\n  const scriptMask =\n    t < SWEEP_START\n      ? undefined\n      : `linear-gradient(${slant}deg, transparent ${edgePct - soft}%, #000 ${edgePct + soft}%)`;\n  const barO =\n    interpolate(sweep, [0, 0.12, 0.85, 1], [0, 1, 1, 0], CLAMP) *\n    (sweeping ? 1 : 0);\n  // the finished logo: a silk sheen drifting slowly through it\n  const sheen = interpolate(t, [SWEEP_START, SWEEP_END + 60], [0, 1], CLAMP);\n  const bloom = interpolate(t, [SWEEP_START + 6, SWEEP_END + 14], [1, 0], {\n    ...CLAMP,\n    easing: EASE_OUT,\n  });\n  const logoStops =\n    finish === \"accent\"\n      ? [SILK[2], accent, accent, SILK[0]]\n      : [\"#FFFFFF\", \"#FBF3EC\", \"#C9C1FF\", SILK[2]];\n\n  // the live trail: short dashes of the same path, each a little older\n  const segments: { a: number; b: number; color: string; alpha: number }[] = [];\n  if (t < WRITE_END + TRAIL) {\n    for (let i = 0; i < TRAIL * STEPS; i++) {\n      const age0 = i / STEPS;\n      const age1 = (i + 1) / STEPS;\n      const b = writeAt(t - age0);\n      const a = writeAt(t - age1);\n      if (b - a < 0.01) continue;\n      const { color, alpha } = trailColor((age0 + age1) / 2);\n      if (alpha <= 0.002) continue;\n      segments.push({ a, b, color, alpha: alpha * burnOutTrail(t, age0) });\n    }\n  }\n\n  const dash = (a: number, b: number) => ({\n    strokeDasharray: `${b - a + 0.6} ${len + 10}`,\n    strokeDashoffset: -a,\n  });\n\n  const trailLayer = (w: number, opacity: number, filter?: string) => (\n    <g\n      filter={filter ? `url(#${filter})` : undefined}\n      opacity={opacity}\n      style={{ mixBlendMode: \"screen\" }}\n    >\n      {segments.map((s, i) => (\n        <path\n          key={i}\n          d={path}\n          fill=\"none\"\n          stroke={s.color}\n          strokeOpacity={s.alpha}\n          strokeWidth={w}\n          strokeLinecap=\"butt\"\n          strokeLinejoin=\"round\"\n          {...dash(s.a, s.b)}\n        />\n      ))}\n    </g>\n  );\n\n  const washR = bh * 2.2;\n\n  return (\n    <AbsoluteFill style={{ background: BG, overflow: \"hidden\" }}>\n      <AbsoluteFill\n        style={{\n          background:\n            \"radial-gradient(ellipse 70% 60% at 50% 50%, rgba(255,255,255,0.035), transparent 70%)\",\n        }}\n      />\n      {/* what the exposure leaves on the stage: a faint silk sheen */}\n      <AbsoluteFill\n        style={{\n          opacity: reveal * 0.55,\n          background: `radial-gradient(70% 46% at ${42 + 8 * sheen}% 60%, color-mix(in oklab, ${SILK[0]} 30%, transparent), transparent 70%), radial-gradient(42% 30% at ${62 - 6 * sheen}% 40%, color-mix(in oklab, ${SILK[2]} 14%, transparent), transparent 70%)`,\n        }}\n      />\n      <svg\n        width={width}\n        height={height}\n        viewBox={`${vbX} ${vbY} ${vbW} ${vbH}`}\n        style={{\n          position: \"absolute\",\n          inset: 0,\n          maskImage: scriptMask,\n          WebkitMaskImage: scriptMask,\n        }}\n        aria-hidden\n      >\n        <defs>\n          <filter\n            id={ids.wide}\n            x=\"-50%\"\n            y=\"-50%\"\n            width=\"200%\"\n            height=\"200%\"\n            filterUnits=\"objectBoundingBox\"\n          >\n            <feGaussianBlur stdDeviation={sw * 2.6} />\n          </filter>\n          <filter\n            id={ids.mid}\n            x=\"-50%\"\n            y=\"-50%\"\n            width=\"200%\"\n            height=\"200%\"\n            filterUnits=\"objectBoundingBox\"\n          >\n            <feGaussianBlur stdDeviation={sw * 0.8} />\n          </filter>\n          <radialGradient id={ids.head}>\n            <stop offset=\"0%\" stopColor=\"#fff\" stopOpacity={0.95} />\n            <stop offset=\"18%\" stopColor=\"#fff\" stopOpacity={0.5} />\n            <stop offset=\"45%\" stopColor={SILK[1]} stopOpacity={0.2} />\n            <stop offset=\"100%\" stopColor={SILK[2]} stopOpacity={0} />\n          </radialGradient>\n          <radialGradient id={ids.wash}>\n            <stop offset=\"0%\" stopColor=\"#fff\" stopOpacity={0.035} />\n            <stop offset=\"100%\" stopColor=\"#fff\" stopOpacity={0} />\n          </radialGradient>\n        </defs>\n\n        {/* the light spills a little onto the stage around the head */}\n        <circle\n          cx={head.x}\n          cy={head.y}\n          r={washR}\n          fill={`url(#${ids.wash})`}\n          opacity={headOn}\n        />\n\n        {/* exposure memory: what the light has already written, barely there */}\n        <path\n          d={path}\n          fill=\"none\"\n          stroke={SILK[2]}\n          strokeOpacity={memory * (1 - reveal)}\n          strokeWidth={sw * 0.9}\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          {...dash(0, headS)}\n        />\n\n        {trailLayer(sw * 5.5, 0.32, ids.wide)}\n        {trailLayer(sw * 2.2, 0.55, ids.mid)}\n        {trailLayer(sw, 1)}\n\n        {/* full exposure: the whole trail at once, then it cools */}\n        <g opacity={glow}>\n          <path\n            d={path}\n            fill=\"none\"\n            stroke={SILK[2]}\n            strokeWidth={sw * 5.5}\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            filter={`url(#${ids.wide})`}\n            opacity={0.24}\n          />\n          <path\n            d={path}\n            fill=\"none\"\n            stroke={SILK[1]}\n            strokeWidth={sw * 2.2}\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            filter={`url(#${ids.mid})`}\n            opacity={0.4}\n          />\n        </g>\n        <path\n          d={path}\n          fill=\"none\"\n          stroke=\"#ffffff\"\n          strokeWidth={sw}\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          opacity={reveal}\n        />\n\n        {/* the point of light */}\n        <g opacity={headOn}>\n          <circle\n            cx={head.x}\n            cy={head.y}\n            r={sw * 7}\n            fill={`url(#${ids.head})`}\n          />\n          <circle cx={head.x} cy={head.y} r={sw * 0.95} fill=\"#fff\" />\n        </g>\n      </svg>\n\n      {/* the logo the light leaves behind */}\n      {t >= SWEEP_START ? (\n        <div\n          style={{\n            position: \"absolute\",\n            inset: 0,\n            maskImage: logoMask,\n            WebkitMaskImage: logoMask,\n          }}\n        >\n          <svg\n            width={logoW}\n            height={logoH}\n            viewBox={`${LOGO.x} ${LOGO.y} ${LOGO.w} ${LOGO.h}`}\n            style={{\n              position: \"absolute\",\n              left: logoLeft,\n              top: logoTop,\n              overflow: \"visible\",\n            }}\n            aria-hidden\n          >\n            <defs>\n              <linearGradient\n                id={ids.logo}\n                gradientUnits=\"userSpaceOnUse\"\n                x1={LOGO.x - 40 + 30 * sheen}\n                y1={LOGO.y - 40}\n                x2={LOGO.x + LOGO.w + 30 * sheen}\n                y2={LOGO.y + LOGO.h + 60}\n              >\n                <stop offset=\"0%\" stopColor={logoStops[0]} />\n                <stop offset=\"40%\" stopColor={logoStops[1]} />\n                <stop offset=\"75%\" stopColor={logoStops[2]} />\n                <stop offset=\"100%\" stopColor={logoStops[3]} />\n              </linearGradient>\n              <filter\n                id={ids.bloom}\n                x=\"-20%\"\n                y=\"-60%\"\n                width=\"140%\"\n                height=\"220%\"\n              >\n                <feGaussianBlur stdDeviation={6} />\n              </filter>\n            </defs>\n            <g opacity={bloom * 0.8} filter={`url(#${ids.bloom})`}>\n              <LogoPaths fill={SILK[1]} />\n            </g>\n            <LogoPaths fill={`url(#${ids.logo})`} />\n          </svg>\n        </div>\n      ) : null}\n\n      {/* the bar of light doing the hand-over */}\n      {barO > 0 ? (\n        <div\n          style={{\n            position: \"absolute\",\n            left: edge - 90,\n            top: -height * 0.2,\n            width: 180,\n            height: height * 1.4,\n            opacity: barO,\n            transform: `rotate(${slant - 90}deg)`,\n            mixBlendMode: \"screen\",\n            background: `linear-gradient(90deg, transparent 0%, color-mix(in oklab, ${SILK[0]} 30%, transparent) 22%, color-mix(in oklab, ${SILK[2]} 55%, transparent) 38%, color-mix(in oklab, ${SILK[1]} 85%, transparent) 47%, #fff 50%, color-mix(in oklab, ${SILK[1]} 85%, transparent) 53%, color-mix(in oklab, ${SILK[2]} 55%, transparent) 62%, color-mix(in oklab, ${SILK[0]} 30%, transparent) 78%, transparent 100%)`,\n            maskImage:\n              \"linear-gradient(180deg, transparent 18%, #000 40%, #000 60%, transparent 82%)\",\n          }}\n        />\n      ) : null}\n      <AbsoluteFill\n        style={{\n          background:\n            \"radial-gradient(ellipse 85% 85% at 50% 50%, transparent 55%, rgba(0,0,0,0.5))\",\n        }}\n      />\n      <Grain opacity={0.06} />\n    </AbsoluteFill>\n  );\n}\n\n/** Once the head has stopped, the remaining trail drains a little faster. */\nfunction burnOutTrail(t: number, age: number) {\n  return interpolate(t - age, [WRITE_END, WRITE_END + 8], [1, 0.6], CLAMP);\n}\n",
      "type": "registry:component",
      "target": "components/remocn/light-trail-write.tsx"
    }
  ],
  "type": "registry:component"
}
