{
  "slug": "spotlight-sweep-moves",
  "title": "Dark-stage spotlight reveals",
  "tagline": "Three dark-stage spotlight reveals — A wake-sleep sweep (light in = bright, light out = dark), B edge-hugging glow pan (violet light seeps along UI edges + steady rightward sweep), C corner reveal (radial light expands steadily from a corner to light the whole screen); light itself narrates in the dark.",
  "description": "Three dark-stage spotlight reveals — A wake-sleep sweep (light in = bright, light out = dark), B edge-hugging glow pan (violet light seeps along UI edges + st",
  "category": "effects",
  "tags": [
    "shotcraft",
    "remotion",
    "effects",
    "ui-entrance",
    "transition"
  ],
  "tier": "free",
  "license": "Apache-2.0",
  "spec": {
    "width": 1920,
    "height": 1080,
    "fps": 30,
    "duration": 4.54,
    "aspect": "16:9"
  },
  "kind": "remotion",
  "params_schema": {
    "type": "object",
    "properties": {}
  },
  "default_params": {},
  "preview": {
    "poster": "https://gimgs.net/motion/media/spotlight-sweep-moves/poster-6ea19d85416a.jpg",
    "video": "https://gimgs.net/motion/media/spotlight-sweep-moves/video-ef3aca65c1d1.mp4"
  },
  "variants": [
    {
      "key": "glow-wake-sleep-panel",
      "label": "glow-wake-sleep-panel · Wake-sleep sweep",
      "description": "A radial reveal mask follows the light head moving steadily left to right; a triple-layer violet glow tracks along the top edge, grazes the logo outline, lights a vertical afterglow at the right edge, then the panel sinks back into darkness at the tail",
      "use": "Introducing a single UI panel in a dark-toned brand film — an entrance and exit that wake and sleep",
      "video": "https://gimgs.net/motion/media/spotlight-sweep-moves/video-ef3aca65c1d1.mp4",
      "poster": "https://gimgs.net/motion/media/spotlight-sweep-moves/poster-6ea19d85416a.jpg"
    },
    {
      "key": "slide-spotlight-pan",
      "label": "slide-spotlight-pan · Edge-hugging glow pan",
      "description": "Light first traces the top-left vertical edge, turns the corner and travels along the top edge, violet glow bleeding into the UI's top inner edge; the spotlight head reveals at constant speed moving right while the panel slides left at constant speed — reading as a rightward camera pan",
      "use": "Touring a wide panel or multi-column board horizontally, lighting up feature areas segment by segment",
      "video": "https://gimgs.net/motion/media/spotlight-sweep-moves/video-0640b7d5423a.mp4",
      "poster": "https://gimgs.net/motion/media/spotlight-sweep-moves/poster-slide-spotlight-pan-64039fd9a48f.jpg"
    },
    {
      "key": "corner-spotlight-reveal",
      "label": "corner-spotlight-reveal · Corner reveal",
      "description": "A radial spotlight in the top-left corner expands with strictly linear radius; what it reaches is revealed, what it hasn't stays black, until the whole screen is lit — light itself is the transition",
      "use": "A black-stage opener that lights up the interface's entrance; a light transition between passages",
      "video": "https://gimgs.net/motion/media/spotlight-sweep-moves/video-6cbeb257118d.mp4",
      "poster": "https://gimgs.net/motion/media/spotlight-sweep-moves/poster-corner-spotlight-reveal-c368c5592d0a.jpg"
    }
  ],
  "credits": {
    "author": "video-shotcraft (Vincent Wei)",
    "url": "https://github.com/Vincentwei1021/video-shotcraft"
  },
  "page_url": "https://gimgs.net/motion/spotlight-sweep-moves.html",
  "json_url": "https://gimgs.net/motion/spotlight-sweep-moves.json",
  "template_url": "https://gimgs.net/motion/spotlight-sweep-moves/template.html",
  "play_url": null,
  "markdown_url": "https://gimgs.net/motion/spotlight-sweep-moves.md",
  "updated_at": "2026-09-24T07:40:25.585Z",
  "prompt": "## When to use\n\nIntroducing UI panels/feature areas one by one in dark-toned brand films; a black-stage opener that \"lights up\" the interface; a light transition between passages\n\n## Intention\n\nIn the dark, viewers only see what the light lets them see — the spotlight is lighting, camera move, and edit all at once: wherever the light lands, that's the entrance; when the light leaves, that's the exit. All three share an identity element — an \"edge-hugging violet glow\" (light tracing the UI border/logo/top edge, the glow bright and soft, the light \"caressing\" the interface rather than an outline animation). The linchpin is **constant speed**: the spotlight's movement/expansion must be strictly linear — easing would give the light \"intent,\" only constant speed reads as a searchlight's mechanical sweep (case in point for style C: linear but with too large a final radius means it saturates in the first quarter, and the feel is no longer even).\n\n## Duration & energy\n\n- Duration: Single style: 3.5–4.5s; A/B can be chained into a tour passage\n- Energy: Medium-low (restrained, mysterious, the payoff is the moment of lighting up)\n\n## Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)\n\n## 意图\n黑场里观众只能看见光给看的东西——聚光既是照明也是运镜和剪辑：\n光到哪里哪里登场，光走即谢幕。三式共用\"贴边紫色辉光光线\"这个\n身份元素（光线贴着 UI 边框/logo/顶边走，辉光要亮要糊，是光在\n\"抚摸\"界面而不是描边动画）。命门是**匀速**：聚光的移动/扩张\n严格 linear——缓动会让光有\"意图\"，匀速才读作探照灯的机械扫掠\n（C 式判例：linear 但半径终值过大＝前 1/4 就饱和，观感照样不匀速）。\n\n## 动效核心\n**A 醒睡扫过**（glow-wake-sleep-panel）：radial 显影罩跟随光头从左\n向右匀速移动，范围外全黑；贴顶边紫色光线三层辉光（blur26 宽糊+\nblur9 中层+亮芯+粉色偏移层）随扫光同步走，经过 logo 时 boxShadow\n描光、到右缘点亮竖直残光；尾段光走面板沉回黑暗——有醒有睡。\n**B 贴边泛光横摇**（slide-spotlight-pan）：光线锚定面板边缘（先绕\n左上角竖缘、转角后沿顶边横走），紫光晕染渗入 UI 顶部内侧（光从\n边缘渗进界面）；聚光头匀速右移显影、面板同时匀速左滑＝相机右摇感。\n**C 角落匀速显影**（corner-spotlight-reveal）：左上角径向聚光半径\n严格 linear 扩张，照到显影照不到沉黑，最终全亮（光即转场）。\n\n## 参数表\n| 参数 | 典型值 | 调节手感 |\n|------|--------|----------|\n| 聚光移动/扩张 | 全程 linear、零缓动 | **匀速是命门**——全程零缓动；加 ease 读作光有主观意图 |\n| C 式半径终值 | 恰好在片尾覆盖全屏（1300@1080p/100f） | 终值过大＝提前饱和假匀速：亮度采样须全程平滑爬升（实测 8/46/101/…/238） |\n| 贴边光线辉光 | 3–4 层（blur26+blur9+亮芯+粉偏移） | 层少读作细线描边；辉光要够亮够糊才是\"光\" |\n| 光线锚定 | 严格贴 UI 边缘/顶边/logo | 光线脱离边缘漂浮＝失去\"抚摸界面\"语义（A 式返工判例：定位丢失紫光跑到底边） |\n| 显影罩 | radial 渐变硬边略糊（feather ~15%） | 边太硬像圆形遮罩；太糊没有\"照到/照不到\"的界线 |\n\n## 已知坑\n- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿，\n  首次实战须以真实素材回验\n- 与 light-play-moves 分工：那张是元素/文字上的\n  光泽戏（sheen/辉光呼吸）；本卡光是**运镜和剪辑**（显影/谢幕/转场），\n  光决定观众看什么\n- 三式重做判例：聚光扫过必须带贴边光线同行（v1 只有显影罩被裁\n  \"改改再看\"——裸聚光没有身份，贴边紫光才是这个手法的签名）\n- 原片（clickup-30）光线转角有一瞬彩虹色散，demo 未做；实战可\n  在转角帧加 1–2f 色散层提质感\n\n## 参考实现\ndemos/effects/spotlight-sweep-moves/\n（CornerSpotlightReveal.tsx / GlowWakeSleepPanel.tsx / SlideSpotlightPan.tsx）\n原片出处：clickup-30.mp4\n\n## Reference implementation (Remotion)\n\n- demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx\n- demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx\n- demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx\n\nThe component imports shared fixtures from `demos/_fixtures` and helpers from `assets/lib` in the repo; SKILL.md there documents the render workflow.\n",
  "flow": [
    {
      "step": "Read the recipe",
      "note": "Prompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points."
    },
    {
      "step": "Get the code",
      "tool": "git",
      "cmd": "git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install"
    },
    {
      "step": "Register + render",
      "tool": "remotion",
      "cmd": "npx remotion render <CompositionId> out.mp4   # component: demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx, demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx, demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx"
    },
    {
      "step": "Or re-implement",
      "note": "Port the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing."
    }
  ],
  "files": [
    {
      "path": "demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx",
      "url": "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx"
    },
    {
      "path": "demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx",
      "url": "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx"
    },
    {
      "path": "demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx",
      "url": "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx"
    }
  ],
  "contract": "React/Remotion composition (TSX) from the open-source video-shotcraft library (Apache-2.0). It is not a browser-playable template: clone the repo, register the component in a Remotion project and render with `npx remotion render`. The recipe (prompt) describes timing, easing and parameters so you can also re-implement the shot in any engine.",
  "render": {
    "engine": "remotion",
    "frames": 136,
    "repo": "https://github.com/Vincentwei1021/video-shotcraft",
    "files": [
      "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx",
      "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx",
      "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx"
    ],
    "note": "Clone https://github.com/Vincentwei1021/video-shotcraft (npm install). The component lives under demos/{category}/{name}/ and imports shared fixtures from demos/_fixtures and helpers from assets/lib. Copy it (with those imports) into a Remotion project, register a <Composition> with the template's width/height/fps/duration in Root.tsx, then `npx remotion render <CompositionId> out.mp4`. SKILL.md in the repo documents the full Claude Code / Codex workflow. The prompt below is the shot recipe (timing, easing, parameter table, pitfalls) — enough to re-implement the shot in HTML/WAAPI or another engine if you prefer."
  },
  "source": "// ===== demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx =====\n// corner-spotlight-reveal —— 对标 clickup-30.mp4 41.5–44.6s：\n// 黑场上，左上角径向聚光从小到大扩张，把白色 Inbox 界面逐步\"点亮\"，\n// 照到的区域显影、照不到的沉黑，最终全屏亮起。光即转场。\nimport React from 'react';\nimport { AbsoluteFill, useCurrentFrame, interpolate, Easing } from 'remotion';\n\nconst FONT = '\"Avenir Next\", \"Helvetica Neue\", Helvetica, sans-serif';\n\n// 灰阶 Inbox 界面（自绘，替代真 UI）\nconst InboxPanel: React.FC = () => (\n  <div\n    style={{\n      width: 1920,\n      height: 1080,\n      background: '#f6f6f5',\n      fontFamily: FONT,\n      padding: '90px 120px',\n      boxSizing: 'border-box',\n      color: '#2c2c2c',\n    }}\n  >\n    <div style={{ display: 'flex', alignItems: 'center', gap: 26 }}>\n      <div style={{ fontSize: 118, fontWeight: 700, letterSpacing: -2 }}>Inbox</div>\n      <div\n        style={{\n          width: 0, height: 0, marginTop: 26,\n          borderLeft: '16px solid transparent',\n          borderRight: '16px solid transparent',\n          borderTop: '20px solid #3a3a3a',\n        }}\n      />\n    </div>\n    <div style={{ display: 'flex', gap: 64, marginTop: 90, fontSize: 44, color: '#555' }}>\n      <div style={{ background: '#e9e8f6', color: '#5b55c8', padding: '10px 34px', borderRadius: 14, fontWeight: 600 }}>All</div>\n      <div style={{ padding: '10px 0' }}>Tasks</div>\n      <div style={{ padding: '10px 0' }}>Docs</div>\n      <div style={{ padding: '10px 0' }}>People</div>\n      <div style={{ padding: '10px 0' }}>Chat</div>\n    </div>\n    {[0, 1, 2].map((row) => (\n      <div key={row} style={{ display: 'flex', alignItems: 'center', gap: 30, marginTop: row === 0 ? 96 : 64 }}>\n        <div style={{ width: 42, height: 42, border: '3px solid #c9c9c7', borderRadius: 10 }} />\n        <div style={{ width: 14, height: 14, borderRadius: 7, background: '#5b55c8' }} />\n        <div style={{ width: 56, height: 56, borderRadius: 28, background: '#efe4e2' }} />\n        <div>\n          <div style={{ display: 'flex', gap: 22, alignItems: 'center' }}>\n            <div style={{ height: 22, width: 220 + ((row * 67) % 90), background: '#3f3f3f', borderRadius: 11 }} />\n            <div style={{ width: 8, height: 8, borderRadius: 4, background: '#bbb' }} />\n            <div style={{ height: 18, width: 260, background: '#c9c9c7', borderRadius: 9 }} />\n          </div>\n          <div style={{ display: 'flex', gap: 14, marginTop: 16 }}>\n            <div style={{ height: 18, width: 300, background: '#8f8bd8', borderRadius: 9, opacity: 0.75 }} />\n            <div style={{ height: 18, width: 340 - ((row * 91) % 120), background: '#d8d8d6', borderRadius: 9 }} />\n          </div>\n        </div>\n      </div>\n    ))}\n  </div>\n);\n\nexport const CornerSpotlightReveal: React.FC = () => {\n  const frame = useCurrentFrame();\n\n  // 聚光半径扩张：全程匀速（用户裁决\"整个过程要匀速\"——严格 linear，无缓动）\n  // r+feather=1.85r 是光前沿；1.85*1300≈2400 恰在片尾盖满全屏对角，\n  // 保证扩张动作占满全片时长而不是前 1/3 就饱和\n  const r = interpolate(frame, [0, 100], [160, 1300], {\n    extrapolateLeft: 'clamp',\n    extrapolateRight: 'clamp',\n  });\n\n  // 光心沿左上角匀速游移（linear）\n  const cx = interpolate(frame, [0, 96], [140, 420], { extrapolateRight: 'clamp' });\n  const cy = interpolate(frame, [0, 96], [90, 260], { extrapolateRight: 'clamp' });\n\n  // 软边宽度：扩张时边缘更羽化\n  const feather = r * 0.85;\n\n  // UI 轻微透视漂移（原片相机贴着界面缓推）\n  const drift = interpolate(frame, [0, 100], [0, 1]);\n  const scale = 1.75 - 0.28 * drift;\n  const tx = -40 + 70 * drift;\n  const ty = -30 + 50 * drift;\n\n  const mask = `radial-gradient(circle ${r + feather}px at ${cx}px ${cy}px, rgba(255,255,255,1) ${Math.max(\n    0,\n    ((r - feather * 0.25) / (r + feather)) * 100,\n  )}%, rgba(255,255,255,0) 100%)`;\n\n  return (\n    <AbsoluteFill style={{ background: '#000' }}>\n      <AbsoluteFill\n        style={{\n          WebkitMaskImage: mask,\n          maskImage: mask,\n          transform: `scale(${scale}) translate(${tx}px, ${ty}px) rotate(${-1.2 + 1.2 * drift}deg)`,\n          transformOrigin: '18% 12%',\n        }}\n      >\n        <InboxPanel />\n      </AbsoluteFill>\n      {/* 聚光自身的白热光晕（叠在界面上方，光心最亮） */}\n      <div\n        style={{\n          position: 'absolute',\n          left: cx - r * 0.7,\n          top: cy - r * 0.7,\n          width: r * 1.4,\n          height: r * 1.4,\n          borderRadius: '50%',\n          background: 'radial-gradient(closest-side, rgba(255,255,255,0.85), rgba(255,255,255,0.25) 45%, transparent 75%)',\n          filter: 'blur(26px)',\n          opacity: interpolate(frame, [0, 10, 60, 90], [0, 0.9, 0.55, 0], {\n            extrapolateRight: 'clamp',\n          }),\n          pointerEvents: 'none',\n        }}\n      />\n    </AbsoluteFill>\n  );\n};\n\n\n// ===== demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx =====\n// glow-wake-sleep-panel v3 —— 扫光方向改为从左向右（用户裁决）：\n// 聚光灯从左向右\"扫过\"斜置面板；一条带辉光的紫色光线贴着 UI 顶边/边框/\n// logo 划过，光到即亮、光走即暗，尾段沉回黑暗（右缘残留蓝紫）。\nimport React from 'react';\nimport { AbsoluteFill, useCurrentFrame, interpolate } from 'remotion';\n\nconst W = 1250;\nconst H = 860;\nconst R = 26;\n\nconst ink = '#3a3a3a';\nconst mid = '#9a9a98';\nconst line = '#e2e2e0';\n\nconst Row: React.FC<{ w: number; icon?: boolean }> = ({ w, icon = true }) => (\n  <div style={{ display: 'flex', alignItems: 'center', gap: 12, height: 30 }}>\n    {icon && <div style={{ width: 18, height: 18, borderRadius: 5, background: mid }} />}\n    <div style={{ height: 11, width: w, background: '#c9c9c7', borderRadius: 6 }} />\n  </div>\n);\n\nconst TaskCard: React.FC<{ seed: number }> = ({ seed }) => (\n  <div style={{ display: 'flex', flexDirection: 'column', gap: 9, padding: '14px 0' }}>\n    <div style={{ height: 9, width: 150 + (seed % 3) * 22, background: line, borderRadius: 5 }} />\n    <div style={{ height: 12, width: 190 + ((seed * 7) % 4) * 18, background: '#b9b9b7', borderRadius: 6 }} />\n    <div style={{ width: 15, height: 11, background: '#d9d9d7', borderRadius: 2 }} />\n  </div>\n);\n\n// 灰阶斜置面板（ClickUp 布局形：侧栏 + Review/Shipped 两列）\nconst Panel: React.FC = () => (\n  <div style={{\n    width: W, height: H, background: '#f6f6f5', borderRadius: R,\n    display: 'flex', overflow: 'hidden', boxSizing: 'border-box',\n  }}>\n    <div style={{ width: 300, borderRight: `2px solid ${line}`, padding: '30px 28px', boxSizing: 'border-box' }}>\n      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 34 }}>\n        <div style={{ width: 30, height: 30, borderRadius: 8, background: ink }} />\n        <div style={{ height: 16, width: 96, background: ink, borderRadius: 7 }} />\n      </div>\n      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>\n        <Row w={72} /><Row w={128} /><Row w={64} />\n      </div>\n      <div style={{ height: 13, width: 84, background: '#b3b3b1', borderRadius: 6, margin: '34px 0 16px' }} />\n      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>\n        <Row w={110} /><Row w={140} /><Row w={104} /><Row w={126} />\n      </div>\n    </div>\n    <div style={{ flex: 1, padding: '30px 36px', boxSizing: 'border-box' }}>\n      <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 30 }}>\n        <div style={{ width: 24, height: 20, background: mid, borderRadius: 4 }} />\n        <div style={{ height: 17, width: 250, background: '#6f6f6d', borderRadius: 8 }} />\n        <div style={{ height: 12, width: 96, background: line, borderRadius: 6, marginLeft: 40 }} />\n        <div style={{ height: 12, width: 76, background: line, borderRadius: 6 }} />\n      </div>\n      <div style={{ display: 'flex', gap: 44 }}>\n        {[0, 1].map((col) => (\n          <div key={col} style={{ flex: 1 }}>\n            <div style={{ borderTop: `4px solid ${col === 0 ? '#b9a44c' : '#6b5bd6'}`, paddingTop: 16, display: 'flex', alignItems: 'center', gap: 10 }}>\n              <div style={{ height: 14, width: 88, background: '#5a5a58', borderRadius: 7 }} />\n              <div style={{ width: 22, height: 22, borderRadius: 11, border: `2px solid ${line}` }} />\n            </div>\n            {[0, 1, 2].map((i) => <TaskCard key={i} seed={col * 3 + i + 1} />)}\n          </div>\n        ))}\n      </div>\n    </div>\n  </div>\n);\n\n// 贴边紫色光线（多层辉光：宽糊层+中层+亮芯），水平段，中心在 cx\nconst EdgeStreak: React.FC<{ cx: number; y: number; len: number; opacity: number; vertical?: boolean }> =\n  ({ cx, y, len, opacity, vertical = false }) => {\n    const long = { position: 'absolute' as const, left: 0, top: 0, opacity };\n    const grad = (c: string) => vertical\n      ? `linear-gradient(180deg, rgba(0,0,0,0) 0%, ${c} 45%, ${c} 55%, rgba(0,0,0,0) 100%)`\n      : `linear-gradient(90deg, rgba(0,0,0,0) 0%, ${c} 45%, ${c} 55%, rgba(0,0,0,0) 100%)`;\n    if (vertical) {\n      return (\n        <div style={long}>\n          <div style={{ position: 'absolute', left: y - 30, top: cx - len / 2, width: 60, height: len, background: grad('rgba(147,80,235,0.55)'), filter: 'blur(26px)' }} />\n          <div style={{ position: 'absolute', left: y - 11, top: cx - len / 2, width: 22, height: len, background: grad('rgba(190,120,255,0.85)'), filter: 'blur(9px)' }} />\n          <div style={{ position: 'absolute', left: y - 2.5, top: cx - len * 0.4, width: 5, height: len * 0.8, background: grad('#f0deff'), filter: 'blur(1.4px)' }} />\n        </div>\n      );\n    }\n    return (\n      <div style={long}>\n        <div style={{ position: 'absolute', left: cx - len / 2, top: y - 34, width: len, height: 68, background: grad('rgba(150,82,238,0.60)'), filter: 'blur(26px)' }} />\n        <div style={{ position: 'absolute', left: cx - len / 2, top: y - 12, width: len, height: 24, background: grad('rgba(196,126,255,0.9)'), filter: 'blur(9px)' }} />\n        <div style={{ position: 'absolute', left: cx - len * 0.4, top: y - 3, width: len * 0.8, height: 6, background: grad('#f4e4ff'), filter: 'blur(1.6px)' }} />\n        {/* 粉色偏移层：截图里光带紫中带粉 */}\n        <div style={{ position: 'absolute', left: cx - len * 0.3, top: y - 7, width: len * 0.6, height: 12, background: grad('rgba(240,150,230,0.75)'), filter: 'blur(5px)' }} />\n      </div>\n    );\n  };\n\nexport const GlowWakeSleepPanel: React.FC = () => {\n  const frame = useCurrentFrame();\n\n  // 聚光沿面板顶边从左向右匀速扫过（面板本地座标）\n  const sx = interpolate(frame, [4, 120], [-260, W + 260], {\n    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',\n  });\n  const sy = 150; // 聚光照在面板上部\n\n  // 全局明暗包络：醒 → 展示 → 睡\n  const env = interpolate(frame, [0, 16, 100, 130], [0, 1, 1, 0], {\n    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',\n  });\n  // 尾段右缘残光：最后只剩右缘一线蓝紫\n  const rightNear = Math.max(0, Math.min(1, (sx - (W - 420)) / 420));\n  const tailBlue = interpolate(frame, [100, 116, 132], [0, 0.8, 0.25], {\n    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',\n  });\n\n  // logo 描光：聚光经过 logo（本地 x≈60）时点亮\n  const logoGlow = Math.exp(-((sx - 60) ** 2) / (2 * 230 ** 2)) * env;\n\n  // 摄影机慢漂移：面板随扫光从左上往右下走（对应扫光方向）\n  const drift = interpolate(frame, [0, 132], [-150, 150]);\n  const driftY = interpolate(frame, [0, 132], [-36, 36]);\n\n  return (\n    <AbsoluteFill style={{ background: '#040308', overflow: 'hidden' }}>\n      <div style={{ position: 'absolute', inset: 0, perspective: 1700, perspectiveOrigin: '46% 40%' }}>\n        <div style={{\n          position: 'absolute', left: 400, top: 150,\n          transform: `translate(${drift}px, ${driftY}px) scale(1.05) rotateY(-13deg) rotateX(9deg) rotateZ(-17deg)`,\n          transformStyle: 'preserve-3d',\n        }}>\n          {/* 聚光环境雾光：跟随光头，泛在面板后黑场 */}\n          <div style={{\n            position: 'absolute', left: sx - 520, top: -300, width: 1040, height: 700,\n            background: 'radial-gradient(ellipse at 50% 55%, rgba(110,62,205,0.42), rgba(110,62,205,0) 65%)',\n            filter: 'blur(34px)', opacity: env,\n          }} />\n          {/* 后层重影面板（截图④⑤双层） */}\n          <div style={{ position: 'absolute', left: -46, top: 34 }}>\n            <div style={{ position: 'relative', filter: 'brightness(0.92)' }}>\n              <Panel />\n              {/* 重影面板同样受聚光范围控制 */}\n              <div style={{\n                position: 'absolute', inset: 0, borderRadius: R,\n                background: `radial-gradient(circle 680px at ${sx - 46}px ${sy + 34}px, rgba(4,3,8,${1 - 0.45 * env}) 0%, rgba(4,3,8,${1 - 0.14 * env}) 55%, rgba(4,3,8,0.99) 88%)`,\n              }} />\n            </div>\n          </div>\n          {/* 面板本体：聚光范围内显影，范围外沉黑 */}\n          <div style={{ position: 'relative' }}>\n            <Panel />\n            <div style={{\n              position: 'absolute', inset: 0, borderRadius: R,\n              background: `radial-gradient(circle 640px at ${sx}px ${sy}px, rgba(4,3,8,${0.12 * (1 - env)}) 0%, rgba(4,3,8,${1 - 0.72 * env}) 58%, rgba(4,3,8,0.985) 92%)`,\n            }} />\n            {/* 尾段右缘蓝紫残光罩 */}\n            <div style={{\n              position: 'absolute', inset: 0, borderRadius: R,\n              background: 'linear-gradient(260deg, rgba(120,130,235,0.30) 0%, rgba(120,130,235,0) 16%)',\n              opacity: tailBlue,\n            }} />\n          </div>\n          {/* 贴顶边划过的紫色光线（本体） */}\n          <EdgeStreak cx={sx} y={-2} len={980} opacity={env} />\n          {/* 右缘竖直光线：聚光接近右侧时点亮，尾段转蓝紫 */}\n          <EdgeStreak cx={260} y={W + 2} len={620} opacity={Math.max(rightNear * env, tailBlue * 0.9)} vertical />\n          {/* logo 一圈描光（截图⑤：光经过 logo 时） */}\n          <div style={{\n            position: 'absolute', left: 8, top: 12, width: 150, height: 66, borderRadius: 16,\n            boxShadow: '0 0 26px 8px rgba(196,126,255,0.75), 0 0 60px 22px rgba(150,82,238,0.4)',\n            opacity: logoGlow,\n          }} />\n          {/* 光头本体眩光：贴着顶边的亮团 */}\n          <div style={{\n            position: 'absolute', left: sx - 190, top: -84, width: 380, height: 170,\n            background: 'radial-gradient(ellipse, rgba(236,205,255,0.95), rgba(180,110,250,0.35) 45%, rgba(0,0,0,0) 72%)',\n            filter: 'blur(12px)', opacity: env * 0.95,\n          }} />\n        </div>\n      </div>\n    </AbsoluteFill>\n  );\n};\n\n\n// ===== demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx =====\n// slide-spotlight-pan v2 —— 按用户截图 clickup03 重做：\n// 紫色光线贴着 UI 面板边缘泛光（先绕左上角竖缘、再沿顶边横走），\n// 聚光头匀速右移，照到处显影、离开处沉暗；面板匀速左滑（相机右摇感）。\n// 用户裁决：\"紫色的光线是贴着ui界面泛光的，聚光的移动是匀速的\"。\nimport React from 'react';\nimport { AbsoluteFill, useCurrentFrame, interpolate } from 'remotion';\n\nconst ink = '#3c3c3a';\nconst mid = '#98989a';\nconst line = '#e4e4e2';\n\nconst PW = 3000;\nconst PH = 1400;\nconst TOP = 150;   // 面板顶边在屏幕座标的 y\nconst CR = 60;     // 面板圆角\n\nconst SideRow: React.FC<{ w: number }> = ({ w }) => (\n  <div style={{ display: 'flex', alignItems: 'center', gap: 16, height: 44 }}>\n    <div style={{ width: 26, height: 26, borderRadius: 7, background: mid }} />\n    <div style={{ height: 15, width: w, background: '#c6c6c4', borderRadius: 7 }} />\n  </div>\n);\n\nconst Task: React.FC<{ seed: number }> = ({ seed }) => (\n  <div style={{ display: 'flex', flexDirection: 'column', gap: 13, padding: '26px 0' }}>\n    <div style={{ height: 13, width: 210 + (seed % 3) * 30, background: line, borderRadius: 6 }} />\n    <div style={{ height: 17, width: 260 + ((seed * 7) % 4) * 26, background: '#aeaeac', borderRadius: 8 }} />\n    <div style={{ width: 22, height: 16, background: '#d6d6d4', borderRadius: 3 }} />\n  </div>\n);\n\nconst Col: React.FC<{ accent: string; seed: number; w: number }> = ({ accent, seed, w }) => (\n  <div style={{ width: w, flexShrink: 0 }}>\n    <div style={{ borderTop: `6px solid ${accent}`, paddingTop: 24, display: 'flex', alignItems: 'center', gap: 14 }}>\n      <div style={{ height: 20, width: 120, background: '#525250', borderRadius: 9 }} />\n      <div style={{ width: 32, height: 32, borderRadius: 16, border: `3px solid ${line}` }} />\n      <div style={{ marginLeft: 'auto', width: 22, height: 22, background: line, borderRadius: 4 }} />\n    </div>\n    {[0, 1].map((i) => <Task key={i} seed={seed + i} />)}\n  </div>\n);\n\n// 超宽面板内容（放大特写级别）：侧栏 + 顶栏 + 三列看板\nconst WidePanel: React.FC = () => (\n  <div style={{\n    width: PW, height: PH, background: '#f4f4f3',\n    display: 'flex', boxSizing: 'border-box',\n    borderRadius: `${CR}px ${CR}px 0 0`,\n  }}>\n    <div style={{ width: 560, borderRight: `3px solid ${line}`, padding: '52px 48px', boxSizing: 'border-box' }}>\n      <div style={{ display: 'flex', alignItems: 'center', gap: 18, marginBottom: 56 }}>\n        <div style={{ width: 46, height: 46, borderRadius: 12, background: ink }} />\n        <div style={{ height: 26, width: 150, background: ink, borderRadius: 10 }} />\n      </div>\n      <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>\n        <SideRow w={110} /><SideRow w={200} /><SideRow w={100} />\n      </div>\n      <div style={{ height: 20, width: 130, background: '#adadab', borderRadius: 9, margin: '58px 0 24px' }} />\n      <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>\n        <SideRow w={180} /><SideRow w={220} /><SideRow w={170} />\n      </div>\n    </div>\n    <div style={{ flex: 1, padding: '52px 64px', boxSizing: 'border-box' }}>\n      <div style={{ display: 'flex', alignItems: 'center', gap: 22, marginBottom: 48 }}>\n        <div style={{ width: 36, height: 30, background: mid, borderRadius: 6 }} />\n        <div style={{ height: 26, width: 400, background: '#606060', borderRadius: 11 }} />\n        <div style={{ height: 18, width: 150, background: line, borderRadius: 8, marginLeft: 64 }} />\n        <div style={{ height: 18, width: 120, background: line, borderRadius: 8 }} />\n        <div style={{ height: 18, width: 90, background: line, borderRadius: 8 }} />\n      </div>\n      <div style={{ display: 'flex', gap: 84 }}>\n        <Col accent=\"#c4ad45\" seed={1} w={620} />\n        <Col accent=\"#6b5bd6\" seed={4} w={620} />\n        <Col accent=\"#4f8f6f\" seed={7} w={620} />\n      </div>\n    </div>\n  </div>\n);\n\nexport const SlideSpotlightPan: React.FC = () => {\n  const frame = useCurrentFrame();\n  // 面板匀速左滑（相机右摇）——严格 linear\n  const slide = interpolate(frame, [0, 132], [180, -1100]);\n  // 聚光头在面板本地座标沿顶边匀速右移——严格 linear\n  // 起点在左上角竖缘（负值=还在左缘竖直段），随后转过角沿顶边走\n  const head = interpolate(frame, [0, 132], [-360, 2600]);\n  const onTop = Math.max(0, head);            // 顶边段进度\n  const cornerT = Math.min(1, Math.max(0, (head + 360) / 360)); // 竖缘段 0→1\n  const vertHeadY = TOP + 620 - cornerT * 620; // 左缘光头从下往上爬到角\n\n  // 屏幕座标的光头位置\n  const headScreenX = slide + onTop;\n  // 光头在竖缘阶段贴着面板左缘\n  const leftEdgeX = slide;\n\n  // 竖缘光线强度：角前满、转角后衰减\n  const vGlow = head < 0 ? 1 : Math.max(0, 1 - head / 900);\n  // 顶边光线强度：转角后满\n  const hGlow = Math.min(1, Math.max(0, (head + 120) / 240));\n\n  const grad = (dir: string, c: string) =>\n    `linear-gradient(${dir}, rgba(0,0,0,0) 0%, ${c} 42%, ${c} 58%, rgba(0,0,0,0) 100%)`;\n\n  return (\n    <AbsoluteFill style={{ background: '#050409', overflow: 'hidden' }}>\n      {/* 面板层：聚光范围内显影 */}\n      <div style={{ position: 'absolute', left: 0, top: TOP, transform: `translateX(${slide}px)` }}>\n        <WidePanel />\n        {/* 贴面泛光：光头下方的紫光晕染进 UI 顶部（贴着界面泛光的关键层） */}\n        <div style={{\n          position: 'absolute', left: onTop - 620, top: -30, width: 1240, height: 380,\n          background: 'radial-gradient(ellipse 620px 190px at 50% 0%, rgba(168,95,245,0.5), rgba(140,75,235,0.16) 55%, rgba(0,0,0,0) 78%)',\n          filter: 'blur(6px)', opacity: hGlow,\n        }} />\n        {/* 左缘贴面泛光（竖缘阶段） */}\n        <div style={{\n          position: 'absolute', left: -30, top: vertHeadY - TOP - 320, width: 340, height: 780,\n          background: 'radial-gradient(ellipse 170px 390px at 0% 50%, rgba(168,95,245,0.45), rgba(140,75,235,0.14) 55%, rgba(0,0,0,0) 78%)',\n          filter: 'blur(6px)', opacity: vGlow,\n        }} />\n        {/* 聚光范围外压暗：以光头为中心的显影罩（面板本地座标，跟光头走） */}\n        <div style={{\n          position: 'absolute', inset: -60,\n          background: `radial-gradient(ellipse 1350px 1000px at ${onTop + 60}px ${(head < 0 ? vertHeadY - TOP : 40) + 260}px, rgba(0,0,0,0) 26%, rgba(0,0,0,0.55) 60%, rgba(5,4,9,0.96) 100%)`,\n        }} />\n      </div>\n\n      {/* ===== 贴边紫色光线本体（屏幕层，贴着面板边缘） ===== */}\n      {/* 顶边横向光线：三层辉光 + 亮芯，中心=光头 */}\n      <div style={{ opacity: hGlow }}>\n        <div style={{\n          position: 'absolute', left: headScreenX - 640, top: TOP - 56, width: 1280, height: 112,\n          background: grad('90deg', 'rgba(150,82,238,0.55)'), filter: 'blur(30px)',\n        }} />\n        <div style={{\n          position: 'absolute', left: headScreenX - 470, top: TOP - 17, width: 940, height: 34,\n          background: grad('90deg', 'rgba(196,126,255,0.9)'), filter: 'blur(10px)',\n        }} />\n        <div style={{\n          position: 'absolute', left: headScreenX - 330, top: TOP - 8, width: 660, height: 16,\n          background: grad('90deg', 'rgba(240,155,235,0.85)'), filter: 'blur(5px)',\n        }} />\n        <div style={{\n          position: 'absolute', left: headScreenX - 300, top: TOP - 3, width: 600, height: 6,\n          background: grad('90deg', '#f6e8ff'), filter: 'blur(1.5px)',\n        }} />\n      </div>\n      {/* 左上角竖缘光线（起始阶段，贴面板左缘） */}\n      <div style={{ opacity: vGlow }}>\n        <div style={{\n          position: 'absolute', left: leftEdgeX - 52, top: vertHeadY - 420, width: 104, height: 840,\n          background: grad('180deg', 'rgba(150,82,238,0.5)'), filter: 'blur(28px)',\n        }} />\n        <div style={{\n          position: 'absolute', left: leftEdgeX - 14, top: vertHeadY - 330, width: 28, height: 660,\n          background: grad('180deg', 'rgba(196,126,255,0.9)'), filter: 'blur(9px)',\n        }} />\n        <div style={{\n          position: 'absolute', left: leftEdgeX - 3, top: vertHeadY - 260, width: 6, height: 520,\n          background: grad('180deg', '#f6e8ff'), filter: 'blur(1.5px)',\n        }} />\n      </div>\n\n      {/* 顶上方黑檐：光带以上纯黑（截图里顶边之上是黑场） */}\n      <div style={{\n        position: 'absolute', left: 0, top: 0, width: 1920, height: TOP - 4,\n        background: 'linear-gradient(180deg, #050409 78%, rgba(5,4,9,0) 100%)',\n      }} />\n    </AbsoluteFill>\n  );\n};\n\n\n"
}