# REPORT — 08-cyberpunk-hud ·「目标锁定 / TARGET LOCKED」

## Concept
A deep-teal film-UI that boots itself in front of you: a sensor array spins up,
a wireframe planet resolves out of the scan, an anomalous echo locks a bearing —
and at 6.40 s the entire instrument flips from cyan to alert orange around a
single line of Chinese: 目标锁定. It is the canonical cyberpunk HUD played
completely straight — Territory-Studio density inside Pentagram restraint —
with one unmistakable hero beat instead of ten forgettable ones.

## Beat sheet (timecodes)
Cue sheet lives in `parts/film.mjs` (`export const CUE`) and is mirrored
verbatim at the top of `audio.py`; picture and sound read the same numbers.
Music grid: **BEAT = 6.4/14 s (131.25 BPM)** so the lock lands exactly on beat 14.

| t (s) | Beat | Picture | Sound |
|---|---|---|---|
| 0.00 | boot | Brand block already on screen; a bright CRT-style sweep flies down the frame; hex lattice fades up | whoosh down + impact + two UI blips |
| 0.12 | grid | Lattice at full strength; ring set begins to draw on clockwise | rising tick cluster |
| 0.30 | rings | Main circle draws on (stroke growth), tick rings counter-rotate | whoosh up |
| 0.60 | brackets | Search brackets + crosshair snap in; side scale ticks | pop + blips |
| 1.05 | radar | Radar sweep goes live; sequential blips appear with expanding echoes | sweep + low blip |
| 1.92 | data | 信号情报 / 目标档案 panels frame up; values roll 4 frames then settle; vertical data-stream columns scroll | 9 rapid UI blips |
| 2.46 | log | Typewriter system log starts, block cursor blinking | typewriter ticks |
| 3.36 | holo | Wireframe planet materialises with a downward scan band + scanning line | big whoosh + impact + bell |
| 4.46 | blip | Contact **T-07** found on the surface; sub-target reticle snaps down | double beep + confirmation blip |
| 5.20 | scan | Sweep across the planet; rings accelerate | sweep whoosh |
| 5.70 | riser | Tension; brackets begin to tremble | riser 240→3800 Hz |
| **6.40** | **LOCK (hero)** | **Lock brackets snap 1.42 → 1.0 (fast-out slow-in, overshoot); global palette flips cyan → orange in 0.22 s; title 目标锁定 pops with glow; coordinates type on; threat bars go hot; glitch burst** | **impact + clap + sub drop + two-tone alarm + two bells** |
| 7.00 | glitch | Tear slices, chroma aberration spike | high-noise burst |
| 7.50 | cascade | Four sub-contact diamonds S-05/S-12/S-27/S-31 pop in around the perimeter; slow cinematic push-in begins | 8 cascading blips |
| 8.25 | confirm | Threat level fills; log confirms 数据链回传中 | bell + blip |
| 8.85 → 10.00 | hold | Composed end frame held 1.15 s, still alive: rings rotate, sweep runs, blips pulse, streams scroll, numbers roll, cursor blinks, spectrum moves, grain drifts | sustained pad, pulse continues at 78 % |

Hero moment sits at **64 %** of the runtime; the end hold is 1.15 s.

## How each signature feature is realised
1. **青色/橙色霓虹线框 (cyan/orange neon linework)** — one `accent` colour is
   computed per frame as a lerp from `#00E5FF` to `#FF6A00`; every stroke, fill,
   tick and blip reads it, so the whole instrument flips in 0.22 s at 6.40 s.
   "Neon" comes from a cheap two-pass fake glow (a 4.5x-wide 16 %-alpha stroke
   under a crisp stroke) rather than `shadowBlur`, which also keeps the frame
   under 2 ms.
2. **目标锁定框与十字准星 (lock brackets + crosshair)** — `drawReticle()`. The
   crosshair has a gap in the middle so the planet stays readable. The search
   frame sits at scale 1.42 with a dashed outline and a slow rotation; at
   `CUE.lock` it snaps to 1.0 through `easeOutBack(lp, 1.05)` (fast-out,
   slow-in, ~5 % overshoot), a white rim flashes for the first 0.6 of the snap,
   and mid-edge ticks grow in afterwards. A second, smaller reticle snaps onto
   the acquired point on the planet surface at 4.46 s.
3. **雷达/环形扫描 loop (radar / ring scan loop)** — `drawRings()`. Three radii:
   a tick ring rotating at −0.30 rad/s, a 24-tick ring at +0.20 rad/s, and eight
   dashed arcs at +0.40 rad/s; plus a progress arc with a travelling head dot.
   The sweep itself is 64 manually-filled wedges with a quadratic trailing
   falloff (`createConicGradient` deliberately avoided for determinism and
   compatibility), rotating at 1.9 rad/s inside a clipped circle. Five blips
   carry a real radar trail: brightness is `exp(-phase)` of the angle since the
   sweep passed, plus an expanding echo ring on first contact.
4. **等宽小字数据流与打字机文字 (monospace data streams + typewriter)** — six
   left/right panel rows and four vertical scrolling digit columns
   (`drawStreams`, 16 rows each, scrolling at ±11–15 px/s) all use `rolling()`,
   which is the required behaviour: a value jumps to a fresh random number for
   **4 frames** and only then settles on its real value, re-rolling every
   0.85–2.0 s. The system log is a character-reveal typewriter
   (`t -> chars = ceil(progress x length)`) with a block cursor blinking at
   ~6 Hz, and the coordinates under the hero title type themselves on the same
   way.
5. **六边形网格与辉光 (hex grid + glow)** — a 34 px pointy-top hex lattice is
   pre-rendered once into two offscreen canvases: a faint full-frame layer and a
   stronger layer masked by a radial `destination-in` gradient so the lattice
   only brightens near the subject. Both are re-blitted each frame with a slow
   parallax so the field is never dead. Global glow is three stacked passes: the
   accent fallback stroke on linework, a large additive breathing glow, and a
   vignette.
6. **线框生长 (line-wire growth / hierarchical stagger)** — arcs are drawn as
   partial arcs (`a0 -> a0 + TAU*p`) rather than a dash trick, so the ring set
   truly grows clockwise from 12 o'clock. Elements enter in hierarchy order
   (grid 0.12, rings 0.30, brackets 0.60, radar 1.05, panels 1.92, log
   2.46, hologram 3.36), and each panel's rows are staggered by 0.09 s
   (about 3 frames) so nothing arrives as a block.
7. **数字滚动 (number rolling)** — see (4): 4-frame roll then settle, driven
   purely by `floor(t x 30)` inside a period, so it is closed-form and identical
   every render.
8. **全局外发光 + 轻微色差 + 扫描线 (glow + chromatic aberration + scanlines)** —
   the scene is rendered to an offscreen canvas, split into an R-only and a
   GB-only copy with `multiply`, and re-combined with `lighter` at ±0.55 px
   (widening to ±3 px during a glitch burst) — real chromatic aberration, no
   filter fakery. A 1x4 scanline pattern drifts 9 px/s over the top, then a
   3 px-cell grain tile drifts at 5 px/s and a vignette closes the frame.

## Technical route
Single HTML page, Canvas 2D only, no WebGL and no third-party runtime library.
`window.renderAt(t)` is a pure function of `t`; the contract, determinism rules
and helper module come from `harness/README.md`. The suggested three.js route
was deliberately not taken: hand-written spherical projection for the
wireframe planet is ~30 lines, keeps the whole film on one canvas (so the
chroma/scanline/grain pass can treat it as a single image), avoids a WebGL
read-back per frame, and measured at **1.9 ms median / 10.6 ms max per frame**
at 1920x1080 — an order of magnitude inside the 250 ms budget.

Per-frame pipeline: background gradient, hex lattice, scan band, boot flash,
(rings + planet + reticle, group-scaled by the post-lock push-in),
sub-contacts, data streams, panels, hero typography, beat-synced frame glow,
glitch tears, R/GB split and recombine, scanlines, grain, vignette.

Sound: `audio.py` builds the whole 10 s in ~5 s of pure-Python synthesis, then
the harness masters it with a single static-gain `loudnorm` pass.

## Check numbers (from `out/08-cyberpunk-hud/qa.json`)
| Check | Value |
|---|---|
| Duration | **10.000 s** (300 frames) |
| Resolution | **1920 x 1080** |
| Frame rate | **30 fps** |
| Video codec | H.264 High, yuv420p, CRF 15, preset medium, aq-mode=3, faststart |
| File size / bitrate | 20.8 MB / **16.7 Mbps** (target 8–25) |
| Audio | AAC 192 kbps, 48 kHz, stereo |
| Integrated loudness | **−13.7 LUFS** (target −14 ± 2) |
| True peak | **−1.8 dBTP** (limit ≤ −1 dBTP) |
| Black frames | **0** |
| Frozen frames | **0** |
| Console errors / 404s | **0** |
| Draw cost | 1.9 ms median, 10.6 ms max @ 1920x1080 |
| `rhythm.mjs video.mp4 0.5` | **no dead spans**; overall mean delta 1.554; min frame delta 0.211 |
| `rhythm.mjs video.mp4 0.25` | **no dead spans** (stricter than required) |
| Renderer verification line | `OK ... 20.8 MB (16.7 Mbps) ... 10.000s ... -13.7LUFS/-1.8dBTP` — **no PROBLEMS** |

## Honest top-3 weaknesses
1. **The alert state holds one composition for ~3.4 s.** The sub-contact
   diamonds at 7.5 s and the slow push-in do escalate it, and micro-motion keeps
   every frame alive, but the layout after the lock is fundamentally the same
   frame as the poster. A second wireframe holo (a drone or a second planet
   resolving in the empty lower-right quadrant at 7.5 s) would have given the
   back half a real second act. This is the biggest thing I would fix.
2. **Chromatic aberration on the 76 px title is visible as an anaglyph fringe
   at peak glitch.** It is intentional and dies back to ±0.55 px, but at the
   lock burst (±3 px) the title reads slightly smeared rather than crisp. A
   per-element CA budget (full for linework, half for type) would be better
   craft.
3. **The vertical data-stream columns are the weakest-designed element.** They
   are correct and on-brief (monospace 3-digit rolls), but at 11 px with 34 %
   alpha they read as texture rather than as information — a jury may see them
   as filler. Fewer, wider columns with a visible column header and a
   per-column settle flash would earn their space instead of occupying it.

## Self-scores (out of 10)
| Axis | Score | Why |
|---|---|---|
| Style fidelity | **9** | Every listed signature technique is present and executed correctly; an expert names the style in under a second. |
| Concept / wow | **7.5** | The hook, the escalation and the 目标锁定 flip are strong, but the back half repeats one composition (see weakness 1). |
| Motion craft | **8.5** | Purposeful easing throughout (no linear anywhere except the mechanical sweep), 3-frame row stagger, fast-out/slow-in snap with overshoot, transitions carried by the element flip rather than a crossfade; the beat-synced frame pulse is a deliberate device. |
| Design & typography | **8.5** | Strict 5 % safe margins, clear hierarchy (planet > title > panels > streams), restrained palette, correct CJK punctuation, 目标锁定 tracked at 16 px and optically re-centred. Loses a point for the data columns. |
| Finish & texture | **8.5** | Real RGB-split chromatic aberration, drifting scanlines, coarse slow grain (no boiling), vignette, zero banding, zero aliasing problems — and only 16.7 Mbps. |
| Sound & sync | **8.5** | Picture and sound share one cue sheet; boot, hologram, blips, lock, glitch, cascade and confirm all land on their visual onset; the lock impact sits on beat 14 exactly. Docked for a fairly flat LRA (1.4 LU). |
| Technical | **9.5** | Exactly 10.000 s, exact resolution/fps, −13.7 LUFS, −1.8 dBTP, 0 black frames, 0 frozen frames, 0 console errors, 16.7 Mbps, 1.9 ms/frame draw, deterministic and bit-reproducible. |
