## Context
The reference page `vertigo.html` is a fullscreen WebGL effect that renders a tunnel illusion entirely in the fragment shader. Its recognizable look comes from:
- converting centered UVs into polar coordinates
- building ring bands that scroll by depth
- slicing those rings with angular segment lines
- modulating ring brightness with multiple wave layers
- adding sparse flash spikes and neon edge highlights
- mixing a dark purple / crimson base with amber and red accents
For this repository, the right translation is a component-scoped shader on a single square `PlaneGeometry`. The component should preserve the motion language and palette feel of the reference while removing DOM shell concerns, fullscreen sizing, and pointer-drag rotation behavior.
## Goals / Non-Goals
**Goals:**
- Add a new independent component instead of editing existing panel components.
- Render the effect on a square plane that sits flat on the ground by default.
- Preserve the reference page's polar tunnel illusion, segmented rings, wave pulses, and flashing highlights.
- Keep the effect autonomous with no click, hover, touch, or drag behavior.
- Expose a concise set of safe controls through `src/dcsConfig.ts`.
**Non-Goals:**
- Do not reproduce the fullscreen canvas shell, page label, or document styling from the reference page.
- Do not modify `src/views/previewEntry.vue` or `src/views/templateComponet.vue`.
- Do not replace `dreamyFluidPanelComponent` or any existing panel component.
- Do not introduce extra mesh layers or geometry-heavy ring instancing.
- Do not port unused or page-specific interaction parameters from the reference file.
## Decisions
1. Decision: Implement the effect as one square `PlaneGeometry` with a custom shader material.
- Rationale: The source effect is fundamentally fragment-driven, and a single plane keeps the port lightweight and aligned with repository conventions.
- Alternative considered: Building the tunnel from repeated ring meshes or instanced geometry. This was rejected because it adds complexity and does not improve the intended floor-surface use case.
2. Decision: Use square dimensions controlled by a single `size` prop.
- Rationale: The user explicitly requested a square plane, so a single size control is clearer than separate length and width values.
- Alternative considered: Keeping independent width and length controls. This was rejected because it weakens the requested square-plane contract.
3. Decision: Preserve the reference structure by reusing polar mapping, depth scrolling, ring segmentation, layered pulse waves, flash spikes, vignette, haze, and grain in adapted form.
- Rationale: Those elements are what make the reference visually identifiable as `vertigo.html`.
- Alternative considered: Replacing the shader with generic radial noise and bloom. This would lose the reference identity.
4. Decision: Remove pointer drag and keep the rotation drift autonomous.
- Rationale: A reusable service component should animate on its own and ignore preview pointer events unless interactivity is explicitly required.
- Alternative considered: Preserving a user-driven rotation offset. This was rejected because it depends on page-level event wiring and contradicts the requested migration style.
5. Decision: Expose a compact control set centered on motion, density, glow, and palette.
- Rationale: `size`, `tunnelSpeed`, `rotationSpeed`, `ringFrequency`, `segmentCount`, `pulseIntensity`, `flashIntensity`, `edgeGlow`, `opacity`, and four palette colors are enough to reshape the effect without overloading the config panel.
- Alternative considered: Exposing every internal threshold and timing constant from the source shader. This was rejected because it would create a noisy, harder-to-use control surface.
## Risks / Trade-offs
- Risk: Because the source is a fullscreen shader, mapping it onto a finite square plane can make the edges feel more abrupt.
- Mitigation: Add a soft square edge mask and keep haze / vignette active so the pattern sits naturally inside the plane.
- Risk: High ring density combined with high flash intensity can produce over-bright or noisy visuals.
- Mitigation: Clamp all exposed numeric props to conservative ranges in both the component and the registry config.
- Risk: The tunnel illusion can look flatter from a perfectly top-down view than from an angled camera.
- Mitigation: Preserve strong pulse contrast, edge highlights, and atmospheric darkening so the plane still reads clearly from typical scene cameras.
## Migration Plan
- Create the OpenSpec change artifacts for the new component.
- Add `src/components/vertigoHaloComponent.vue` with safe prop clamping, uniform syncing, and time updates.
- Add `src/shader/vertigoHaloComponent/panel.vert` and `panel.frag`.
- Register the component in `src/dcsConfig.ts` with defaults, config controls, and default object transform.
- Add a preview asset under `public/preview/`.
- Run `npm run build` and update `tasks.md` with completion status.
## Open Questions
- None for the current scope.