# PRiME · Procedural anamorphic flare

> Archived experiment — not selected for the homepage. The original solar pass
> has been restored in `app/HubStarTitle.tsx` and `app/PrimeHomepage.tsx`.
> This renderer remains available only in the standalone `/flare-lab` preview.

## Intent and platform

HTML5 Canvas 2D with TypeScript, integrated into Next.js. The renderer has no
third-party runtime dependency. Canvas gives independent, predictable control
over six optical layers without adding a WebGL engine to the existing scene.

This is a Chameleon-inspired art-direction approximation, not a calibrated
Caldwell lens model, physical ray tracing, or a manufacturer-endorsed simulation.
The existing generated Canada-facing Earth image is retained. It should not be
treated as authoritative geography or evidence about the locations of city lights.

## Files

- `app/lib/anamorphic-flare.ts`: parameter block, presets, keyframes, deterministic
  optical geometry, six drawing components, and final screen compositor.
- `app/AnamorphicFlareCanvas.tsx`: responsive transparent canvas, pixel-ratio cap,
  pause/visibility/reduced-motion lifecycle, and optional timeline integration.
- `app/flare-lab/`: visual preview with timeline, four state buttons, three presets,
  layer isolation, and adjustable parameters. Live route: `/flare-lab`.
- `app/HubStarTitle.tsx`: the selected, original homepage solar design; it no
  longer uses this experiment’s source path or renderer.
- `tests/anamorphic-flare.test.mjs`: deterministic geometry and timing checks.

## Starting parameters

| Component | Balanced starting values |
| --- | --- |
| Main streak | Blue `[85,159,255]`; core thickness 1.7 CSS px at 900px reference height; exponential decay length 46% frame width; reach 115% in either direction; intensity .94 |
| Main ghosts | 5; cyan `[93,181,239]`; short-axis radii .9–3% of the shorter frame dimension; opacity .025–.115; fixed elliptical aspect ratios 2.2–3.4 |
| Ghost motion | `[.18,.24,.31,.38,.46,.55]`; different relative speeds, all slower than the source |
| Bloom | Warm white `[255,242,212]`; radius 14.5% of shorter dimension; intensity .82 |
| Veil | Neutral-warm `[244,236,217]`; maximum opacity .036; local radius .49 frame width |
| Micro-ghosts | Disabled by default; intensity .28 |
| Atmosphere | Blue `[123,199,255]`; opacity .13; thickness 1.1 reference pixels |

Values at the top of the renderer are the source of truth. All presets clone
their settings; preview edits cannot change the production homepage. `subtle`
reduces each layer, `balanced` uses the values above, and `strong` raises exposure
without changing the optical vocabulary or introducing rainbow colours.

## Source path and timing

The preview lasts 10 seconds and plays once on request. Progress is normalized
from 0 to 1, so it can instead be driven by a scroll timeline, video time, or
another animation engine. The homepage no longer drives this experimental pass.

| Progress | Sun X | Sun Y | State |
| --- | --- | --- | --- |
| 0 | 1.055 | .115 | Just outside the right edge |
| .26 | 1 | .122 | Touching the frame edge |
| .60 | .965 | .139 | 3.5% inside the frame |
| 1 | .835 | .166 | Farther inside, still upper-right |

Each interval uses a quintic smoothstep with zero endpoint velocity. Positions,
reflections, and exposure are deterministic, so seeking is immediate in either
direction. There is no independent oscillating intensity or pulse. Light
admission rises as the sun enters, while a smooth edge-coupling envelope gives
the strongest flare slightly inside the frame. Farther inward remains visible
but is less intense. This response curve is authored, not measured lens data.

## Layer behaviour and compositing order

1. **Earth and star scene:** retained image plus existing procedural star title.
   The existing moving horizon mask keeps sky stars behind Earth.
2. **Atmospheric edge:** optional, very thin extra light following the same
   ellipse as the approved Earth mask. It supplements the image’s existing rim.
3. **Veiling glare:** localized warm-neutral screen overlay slightly lifts dark
   values. It does not blur the whole picture or lower opacity of text.
4. **Ghost ellipses:** five fixed, soft aperture impressions. Unequal sizes,
   opacities, increasing spacing, small vertical offsets, and different
   motion multipliers suggest multiple internal reflecting surfaces.
5. **Micro-ghosts:** optional tiny secondary impressions, deliberately subordinate.
6. **Source bloom:** broad soft warmth plus a compact white centre. Radius grows
   modestly with exposure; the sun does not become an oversized yellow disc.
7. **Main streak:** the dominant blue horizontal signature, exactly at sun Y.
   A cached sprite multiplies exponential horizontal attenuation by a narrow
   Gaussian core and broader feather. Only the immediate source trends white.

All optical layers use `screen` inside the canvas, and CSS `mix-blend-mode:
screen` combines that canvas with the scene beneath. The flare canvas sits above the
Earth because these are effects in the camera lens/sensor, not objects in space.
In the former homepage integration, controls and content sat above the optical
pass, and it faded out before the starry A handoff. That integration is archived.

## Reuse

```ts
const flare = new AnamorphicFlare();
const settings = createFlareSettings("balanced");
// Inside the caller's drawing loop, after the scene has been rendered:
flare.render(context, {
  width, height,
  source: sampleSunTimeline(progress),
  opacity: 1,
  horizon: earthHorizon(width, height, 1),
}, settings);
```

The caller owns clearing the canvas and the animation clock. `render` restores
the canvas drawing state. Omit `horizon` to omit the atmosphere for other scenes.
The streak sprite rebuilds only after colour or falloff settings change.
No per-frame pixel readback, remote render service, or generated video is used.

## Accessibility and performance

- The optional timeline adapter supports Pause/Skip and removes its optical
  pass for reduced-motion and compact/static layouts. It is not currently
  mounted on the homepage, which retains its original motion controls.
- Preview starts paused. Reduced motion disables playback but preserves static
  scrubbing and keyframe selection. Every control has a native label.
- Playback stops at the final frame; no sudden looping reset. Offscreen/hidden
  preview progress freezes. The homepage does not repaint unchanged flare frames.
- Decorative canvas is hidden from screen readers; the figure supplies a text
  description. Flare controls do not appear over homepage navigation.
- Device pixel ratio is capped at 1.5; one small cached sprite handles the streak.
- This implementation does not certify whole-page WCAG/AODA compliance. Test
  layered text contrast, native assistive technology, and lower-power devices
  as part of the agency's release review.

## References

- Caldwell Photographic: https://www.caldwell.tv/chameleon/
- Brian Caldwell interview describing the standard blue horizontal flare:
  https://thecinelens.com/2019/04/09/caldwell-chameleon-flexible-anamorphic-primes/

The references establish the visual inspiration. Ghost positions and exposure
curves in this project are original, adjustable artistic choices.
