@latimer-woods-tech/cinematic
v0.1.0
Published
The cinematic component tier (Quincy backlog #2) — palette-driven background fields (nebula / cymatic / noise), particle depth systems, phi-timed motion primitives, narration-to-scene cue-map utilities, and the monolith typographic system. Runtime-agnosti
Downloads
94
Readme
@latimer-woods-tech/cinematic
The cinematic component tier — Quincy backlog #2 (docs/creative/QUINCY.md),
laws from docs/creative/CREATIVE_BIBLE.md. One reusable tier for every
surface — Remotion compositions and web pages — so no surface ships at
template ceiling again.
Runtime-agnostic by construction: no Remotion import, no DOM access, no
Node built-ins. Every component is a pure function of frame; drive it from
useCurrentFrame() in Remotion or a requestAnimationFrame clock on the web.
What's inside
| Module | What it is |
|---|---|
| PALETTES / resolvePalette | The creative-direction palettes (gift / shadow / practice / mirror + marketing / training / walkthrough) as executable render direction: colour fields, field ("shader") params, motion energy, particle registers, music direction. Contrast- and law-tested. |
| NebulaField | The deep-field background: void-first gradient, drifting nebula lobes in the palette's two hues, turbulence filaments, seeded stars, vignette. symmetry mirrors the field (the mirror palette's tell). |
| CymaticField | Chladni standing-wave patterns — sound made visible. Sand-grain nodal lines that morph up a mode ladder with film progress, beat-quantised when a cue map provides beats. |
| ParticleDepth | The three-plane parallax particle system (far / mid / near) with palette registers: motes, stardust, aurora, embers. No glare orbs by construction. |
| MonolithTitle / Eyebrow / QuietLine | The monolith typographic system: one serif + one sans (via @latimer-woods-tech/design-tokens), tracked caps, entrance by opacity/tracking/rise only. toDisplayLabel enforces the ≤5-word label law. |
| phiPhases / phiEventFrames / phiGrid / easings | Phi-timed motion primitives. Linear easing is unrepresentable. |
| buildCueMap / beatGrid / weightsFromScript | Music-sync: measured narration duration + script → scene cue map, transitions snapped to the beat grid. |
| contrastRatio / strobeReport | A11y guards — WCAG AA contrast and photosensitivity (≤3 flashes/s), unit-enforced against every palette. |
| CinematicFixtureGallery / FIXTURES | A demo fixture per primitive (storybook-style). Registered as the CinematicFixtures composition in apps/video-studio for Remotion Studio preview. |
Palette → field mapping
| key | register | field | energy | particles | sky mood | |---|---|---|---|---|---| | gift | luminous / expansive | nebula | 0.55 | stardust ↑ | dawn | | shadow | intimate / grounded | noise | 0.30 | motes ↓ | ink | | practice | kinetic / encouraging | cymatic | 0.80 | motes ↑ | lux | | mirror | reflective / spacious | nebula (mirrored) | 0.45 | aurora ↑ | tide | | marketing | bold / cinematic | nebula | 0.70 | stardust ↑ | self | | training | crisp / warm / focused | noise | 0.50 | motes ↑ | chronos | | walkthrough | guided / confident | noise | 0.55 | motes ↑ | aether |
Usage (Remotion)
import { useCurrentFrame, useVideoConfig } from 'remotion';
import {
resolvePalette, buildCueMap, weightsFromScript,
NebulaField, ParticleDepth, MonolithTitle,
} from '@latimer-woods-tech/cinematic';
const Scene: React.FC<{ script: string; narrationDurationSeconds?: number }> = (props) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const palette = resolvePalette('training', undefined);
const cueMap = buildCueMap({
fps,
scenes: [{ id: 'hook' }, { id: 'body', weight: 3 }, { id: 'close' }],
...(props.narrationDurationSeconds !== undefined
? { narrationDurationSeconds: props.narrationDurationSeconds }
: {}),
});
return (
<>
<NebulaField frame={frame} palette={palette} seed={11} />
<MonolithTitle frame={frame} enterAt={cueMap.cues[0].startFrame + 8}
text="Your pattern holds" palette={palette} x={140} y={620} />
<ParticleDepth frame={frame} palette={palette} seed={11} />
</>
);
};On the web, gate animation behind REDUCED_MOTION_QUERY and freeze frame
when the user prefers reduced motion.
Laws enforced by tests
- Void-first grounds (voidBottom luminance < 0.02) and WCAG AA text contrast per palette.
- Motion energy bounded [0.2, 0.85]; entrances ≥300ms; no easing overshoot.
- The ≤5-word label law (
toDisplayLabel) — the ellipsis class is unrepresentable. - Strobe safety:
strobeReportflags >3 flashes/second. - Cue maps exactly cover the film; every scene holds ≥1 frame; interior transitions land on beats when a tempo is given.
