Art Deco 装饰艺术
Midnight at the Starlight Hotel·58s·Lemo-Opuscarby Lemomo
Black lacquer, engraved gold line and airbrushed geometry: a 1930s poster that moves. Every composition has a centre axis, transitions open or close along it, and light arrives as bulbs switching on one by one.
The demo: A grand hotel, 1930: a bellboy races lifts and revolving doors to deliver one letter before midnight.
Black lacquer, engraved gold line and airbrushed geometry: a 1930s poster that moves. Every composition has a centre axis, transitions open or close along it, and light arrives as bulbs switching on one by one. References (grammar only): A. M. Cassandre posters (giant geometry, steep perspective, airbrush inside hard edges); Chrysler Building / Rockefeller Center ornament (setbacks, sunbursts, chevrons); Busby Berkeley overhead numbers overheads (human kaleidoscopes); The Great Gatsby (2013) title sequence (gold line drawing itself on black); Gershwin-era symphonic jazz (clarinet, piano, muted trumpet). Never copy a poster layout, a real building, a character, a typeface design or a melody.
1. Essence, and what it is not
A world built from gold keylines on warm black, filled with airbrushed hard-edged volumes (Cassandre, Lempicka), organised around one vertical axis. Ornament is the picture: sunbursts are backgrounds, stepped arches are frames, a dial is a progress bar, a bulb marquee is a reveal. Motion is mechanical and symmetrical: things unfold from the centre, doors split along the seam, lights switch on in counted order. Native register: glamour with a clock ticking (an event, a deadline, a launch).
Not a gold-foil slideshow (things move and have volume), not Art Nouveau (no whiplash curves, no flowers), not a flat vector poster (volumes are airbrushed and rimmed), not a 60s spy title (no silhouettes on flat colour).
2. Materials & rendering
- Ground: warm lacquer black, never neutral grey-black; a night sky may drift toward a deep emerald near the horizon.
- Gold is a banded metal gradient (dark – light – hot – light – dark); animate its
sheenoffset for a light sweep. - The signature stroke (
gline): a dark engraved underline ~1.6 px wider than the line, the gold gradient line, and a hairline highlight on top. Optional glow and a parallel twin (double). Nothing gets a black cartoon outline. - Volumes: hard edge + airbrush (
airbrush): a directional gradient from shade to light inside the shape, one consistent light direction (upper left by default), a thin gold rim on the lit side. - Motifs (sunburst, stepped arch / ziggurat, fish-scale, chevrons, fan, four-point sparkle, speed lines, clock face, dial) are structural (a background, a frame, a transition), not stickers.
- Perspective is real: true one-point (mode-7 floors) and two-point perspective through a pinhole camera, so dolly, tilt and pan change perspective instead of scaling flats.
- Characters are deco too: about 7 heads tall, tapered streamline bodies, faceted lacquer planes (Lempicka), almond or arc eyes, a one-stroke nose, airbrush + gold rim. Give each lead one or two silhouette marks readable at a quarter of frame height.
3. Colour logic
- Three constants: warm black ground, gold line and metal, ivory for paper, gloves, light and type.
- One saturated accent reserved for the protagonist (or the one object the story follows). It is the only large saturated area, so the eye finds it in any wide shot. A cooler jewel tone may carry secondary surfaces, never competing in area.
- The one-colour exception: any single element can be drawn in its own colour through the same fill + keyline + glow (
coloroption) while everything else stays gold. - Always expand hex to six digits in code (three-digit hex breaks colour mixing).
- Examples of the triad (accent / jewel / metal): burgundy / emerald / gold; coral / sapphire / pale gold; jade / plum / rose gold. Our demo's actual values are in DEMO.md.
4. Type & subtitles
- Type (OFL): Limelight (titles), Poiret One (numbers, sign skeletons, plaques), Josefin Sans (subtitles, labels), Italiana (numerals).
- Titles are architecture: a stepped gold title bar over an arch or sunburst, optional badge and wings; drawn on in gold, then a sheen sweep.
- Subtitle card (
subtitleCard): a lacquer bar (~88 % black) with stepped ends like the title bar, double gold keyline, Josefin Sans SemiBold ~40–42 px ivory, an optional small speaker icon per voice. It unfolds from the centre like every other title, so titles, subtitles and transitions are one system. Hold ≥ max(1.8 s, speech + 0.6 s). - Numbers carry plot without narration: dials, clock faces, floor medallions, badges.
5. Motion quality
- Characters step on twos (12 fps); camera, light, bulbs, gold draw-on and sheen run on ones (24 fps). A stepped camera reads as stutter.
- Everything unfolds from the centre: a point → a hairline → bars open symmetrically → text rises → wings and sparkle.
- Draw-on follows the music: a gold line grows at the speed of the phrase under it and lands on the hit.
- Bulbs have an ignition overshoot (~1.6× flash settling in ~0.18 s) and a relay "chunk"; once a sign is lit, a fast chase may run across it.
- Mechanical easing: doors, dials and hands move with firm ease-in-out and a small settle, like machinery; nothing floats.
- Performance beats get anticipation and escalation in threes (once, twice, mash).
- What never moves: the centre axis of a composition. Symmetry may rotate or open, but it never drifts off-centre.
6. Camera grammar
A vocabulary, not a route. Opening and ending come from the topic.
| Move | What it expresses | Can serve |
|---|---|---|
| Symmetric split (two door leaves hinged at the edges; or a revolving-door wipe) | a threshold crossed | a new place; a new chapter; a reveal behind a façade |
| Leaves sliding shut over the live shot | a door closing on a moment | leaving; a decision made; the end of an era |
| Extreme low-angle Cassandre tilt | scale and aspiration | a goal far above; a tower, a rocket, a monument |
| Architectural section (pull out to a cutaway of the whole building) | progress through a structure | climbing, descending, a process in stages; a company's floors |
| Busby Berkeley overhead, mirrored and rotating | people become pattern | a team, a release, a celebration, a system of parts |
| Push-in on a dial, medallion or clock | the number is the plot | a deadline; a count; a milestone |
| Match-cut on shape (circle → circle, ray → ray) | two places, one rhyme | jumping between departments, cities, eras |
| Low oblique along a sign or marquee | light travelling letter by letter | a name revealed; a launch; a score being counted |
| Pull back from detail to skyline | where the moment sits in the world | aftermath; a city-wide effect; scale |
Framing: the centre axis is sacred; an asymmetric frame must resolve to it within the shot. At an emotional peak the protagonist fills ≥ ~1/3 of frame height (smaller, the face reads as a prop in the ornament). Transitions: splits, revolves, arch openings, shape matches; never a generic dissolve or slide.
7. Sound palette
- Symphonic jazz of the 1920s–30s, not a 60s big band. Options: stride or concert piano, clarinet (trill; a glissando by time-varying resampling of a long note), strings (tremolo, rushes, pizzicato), muted trumpet commentary, trombone and sax section, walking pizz bass, brushes or sticks, tubular bells, harp glissandi, banjo, xylophone runs, celesta.
- Rhythm families to choose from: foxtrot, Charleston, tango, a slow torch-song ballad, a fanfare in the manner of a newsreel.
- Techniques (options): one hit per unit of counted light; accelerate by dividing the beat; plant a theme in fragments so its full statement is a payoff; low-pass a band that is physically far away and open it as we approach; move a period narrator through acoustic spaces (horn, radio, PA, live mic) to make distance audible.
- Foley by material: brass clicks, bronze clang + chain, iron treads, marble heels, silver trays, wooden doors + spring twang, paper flutter, knife-switch "chunk" + filament hum, relay ticks, elevator ding, champagne cork.
- Silence as a tool: before the most important sound, drop to one small diegetic sound (a clock tick, wind) and cut back in with that sound alone.
- J/L-cuts carry architecture: the next room's sound enters a bar before its door opens.
- Mix: duck music ~−9 dB under voice (less under a period announcer who is part of the texture), beds −6 dB, −14 LUFS, light film grain.
8. Native moves
A menu: use the ones your story needs.
- Counted light. A bulb sign lights one letter per beat or per event, so the audience can count. Fits content like: the countdown to a product launch; the letters of a city name lighting as a train arrives; votes tallied into a winner.
- Threshold doors. Every scene change is a door split along the seam. Fits content like: the departments of a company; the rooms of a museum; stages of a career.
- Machine kaleidoscope. People or objects become a mirrored, rotating pattern that locks into a symbol. Fits content like: a team becoming a logo; gears of a supply chain; a choir becoming a clock.
- Dials carry the plot. A floor indicator, a clock or a gauge moves instead of narration. Fits content like: a funding thermometer; the altitude of a climb; a stock ticker at the opening bell.
- The architectural cutaway. Pull out until a building is a section and the protagonist a coloured dot with speed lines. Fits content like: data moving through a server stack; a letter through a post office; a skier down a resort.
- Sheen sweep / draw-on. Light crosses a gold object on a hit; a gold line engraves itself at the speed of a glissando. Fits content like: unveiling a trophy; a map route; a signature on a treaty.
- The one colour. One element keeps its own colour in a gold world. Fits content like: the one product among competitors; the patient among doctors; the new idea in an old firm.
9. Pitfalls of the medium
- Bulb signs from glyph skeletons break on curves (G, S, R): Zhang–Suen staircase pixels fool a neighbour-count junction test → use the crossing number and weld chain ends within ~14 px.
- A generic cartoon character looks pasted in → characters are deco (§2).
- Fish-scale reads as brickwork → lower half-circles row by row, each overlapping the previous row, plus an inner arc.
- Door leaves over a flat "interior" read as a blank frame → draw only the leaves, closing over the live shot.
- A gold point on pure black trips
blackdetect→ lift the background wedges and glow slightly. - Period loudspeaker distortion is unintelligible under music → gentle drive; whisper-check every line on the final mix.
10. Engine
Canvas2D, deterministic in t, in demo/engine/: deco.js (gold gradient, gline, airbrush, motifs, drawShape for any path in the deco manner, color for the one-colour exception), type.js (title bar, digits, badges, dial, clock, subtitleCard), bulbs.js (any text → bulb sign, litSequence), cam.js (pinhole camera, cardTransform). demo/frames.js renders model sheets and style frames from the real engine. Signatures and a minimal example that draws something not in the demo: DEMO.md "Engine reference".
11. Variation space
You decide the structure, the characters (or none), the settings, the opening, the ending, the camera path, the pacing, the accent colour and what gets counted. All far from our demo:
- Structures: the exhibition (five pavilions of a world's fair, one idea of the topic behind each door); the ocean liner (three decks from engine room to ballroom, a horn per stage); the trophy night (nominees as sunburst panels, the winner revealed in light).
- Openings: the machine room (gold gears and pistons building to the first beat); the engraved map (a gold route crosses a continent before anyone appears); the telegram (ticker tape types the premise).
- Endings: the lights go out (letters switch off in reverse until one bulb remains); the dawn (lacquer black warms to a pale sky); the poster (the last shot flattens into a printed poster with a date).
How our demo was made (story, shots, score, end card, build): DEMO.md. Read it after your treatment exists.
Director's notes for the demo film
One example among many. Don't reuse its story, arc, shots, props or timings.
Demo: Midnight at the Starlight Hotel (58.4 s) · art-deco.mp4 · source in demo/
The original brief for the demo: a 40–60 second film in the Art Deco style; the director decides story, shots, score, sound and titles.
Story & structure
A bellboy, Pip, must carry a sealed letter to the rooftop before midnight on New Year's Eve 1930. A small, urgent errand in a grand place. A mechanical obstacle (the elevator is OUT OF ORDER) turns panic into resolve. A rising middle with a tempo change (the stairs = Charleston). A true silence before the climax (the clock hits XII, the band stops, the letter tumbles). The climax is counted light: twelve strikes of midnight = the twelve letters of THE STARLIGHT lighting one by one.
The music is the plot: the letter holds the band's new song; the theme is only heard in fragments until the conductor opens it, and the 13th beat is the first full statement. Echo at the end: the hero who looked up at a dark sign now stands inside the lit one; a button gag closes the loop (the elevator dings IN SERVICE — too late).
How the style's native powers were spent in this story:
| Native power | Demo use |
|---|---|
| The centre axis | Every transition is a door: the title arch splits open, stair doors burst, kitchen swing doors bang, elevator doors close into the end card. |
| Counted light | The bulb sign lights letter by letter, one per bell. |
| Machine symmetry | A Busby Berkeley overhead: fans opening on eighth notes become a sunburst, then lock into a clock face. Used as the release after the climax. |
| Dials & numbers | Floor indicator, clock face, floor medallions, year badge: floor 30, 11:55, 1930 carry the plot without narration. |
| Period radio | An announcer as narrator, moved through acoustic spaces (street horn → desk radio → stairwell PA → live mic) so the audience hears the hero getting closer to the source. |
The recipe we used to adapt it (for this demo): find the threshold (doors), the deadline (a clock), the counted reveal (a sign, floor numbers), and the thing the finale unlocks (a song).
Shots
| Beat | Camera |
|---|---|
| Opening (3 s hook) | A single gold point explodes into rays and stepped arches; slow 6 % push. Title bar blooms on the orchestra hit. |
| Transition grammar | Symmetric split: the outgoing frame becomes two door leaves hinged at the edges that swing open from the seam (arch, stair doors, kitchen doors). The revolving door is its rotary cousin (glass wings wipe). The film closes with elevator doors sliding shut over the live shot. |
| Establishing | Extreme low-angle Cassandre tilt from the dark sign at the top of the tower down to the tiny hero on the street: goal, difficulty and the dark sign (the setup of the ending) in one move. |
| Obstacle | Medium on the plaque dropping; a slow push on the face during the silence while he straightens his cap. |
| Signature 1 | The stairwell as an architectural section: rise with him, pull out until the whole tower is a cutaway and he is a red dot with speed lines, push back in on the "30" floor medallion, match-cut to a spinning silver tray in the kitchen. |
| Silence | Insert of the tower clock's minute hand clicking to XII; the letter tumbling in slow motion past the dark letters. |
| Climax | Twelve bells: catch (ECU glove) → conductor (tear the seal, insert of the score, baton up) → low oblique of the sign as letters light one per strike → close-up as the last T lights behind the hero, gold light across his face. |
| Signature 2 | Busby Berkeley: an oblique high angle as 8 dancers open their fans one per eighth note, then straight overhead, 8-way mirrored and slowly rotating; the fans lock into a clock face with two gold hands at XII. |
| Scale reveal | Pull back from the sign to the whole tower, the city and fireworks (echoes the opening tilt). |
| Ending | Elevator doors slide shut over the live shot; the end card plaque sits on the closed doors. |
Performance beats: the elevator button pressed three times (once, twice, mash); the throw has a wind-up, release and a near-fall over the railing; the cap knocked off by a tray lands back on his head one bar later while he doesn't even look. In the opening the gold lines grow at the speed of the clarinet glissando (slow → fast), landing on the downbeat hit. After all letters are lit, a 16th-note chase runs across the whole sign.
Score structure
- Score first:
timeline.jsis the single source of truth (116 BPM foxtrot → 16 beats accelerating to 138 BPM Charleston → stop → 12 bells on the 116 grid → the song in D♭).tools/cuecheck.pychecks 53 picture sync points againstmusic/score.json(max offset 0.5 ms). - Orchestration as used: piano lead (Salamander), clarinet (low trill + two-octave glissando curtain-raiser), strings (tremolo bed, upward rushes), muted trumpet commentary ("wah-wah" on the plaque), brushes → sticks in the Charleston, walking pizz bass, tubular bells (B♭) for midnight, harp/piano glissandi for each fan, trombone + sax for the final chorus.
- Planting the theme: title = piano bar 1; street = muted trumpet tries two bars and is cut off; kitchen = the hero whistles the first four notes; finale = the full song.
- Distance automation: the band plays on the 30th floor, so it is low-passed at 2.5 kHz on the street, 1.2 kHz in the lobby (through the floor), opens up as he climbs, full-range and dry on the roof.
- Announcer in five spaces (Kokoro
bm_fable): street horn (band-pass 320–3.8 kHz, soft drive, slap echo) → desk radio → stairwell PA (long reverb) → kitchen radio → live mic (full range). Heavy horn distortion made "five minutes to midnight" unintelligible in the full mix, so the drive was reduced. - Foley as used: brass button click, bronze plaque clang + chain rattle, iron stair treads on eighth notes, marble heels, silver trays, wooden swing doors + spring twang, paper flutter, glove slap, knife-switch "chunk" + filament hum per letter, relay ticks for the chase, firework whistles.
- Silences: after "Out of order?!" only the lobby clock ticks twice (next sound: the Charleston snare); after the tower clock clicks to XII only wind and the fluttering letter (next sound: the first bell, the most important sound in the film); one beat of held breath after bell 12 (next: tutti).
- J/L-cuts: radio tuning noise before the arch opens; the echo of "Out of order?!" rolls up the stairwell; the kitchen radio starts during the stairwell; rooftop wind enters a bar before the kitchen doors; bell 12's tail rings into the tutti.
- Mix: music ducked ≈ −9 dB under voice (−6 dB under the live announcer), beds −6 dB; −14 LUFS, grain 3.
Palette & props
- Ground: warm black
#0d0b09, lacquer#060504; night sky#0a0e16→ horizon emerald#10231f. - Gold:
#6F5220(shadow) →#C9A24B(base) →#F3D98B(light) →#FFF4D2(specular). - Accents: burgundy
#8E1B2E(the hero's uniform, the only large saturated area), emerald#1D6B57(fans, door panels, night), ivory#F2E8D5(the letter, gloves, carpet). - Scenes: the lobby in one-point perspective with a mode-7 floor; the rooftop sign in two-point perspective from below with a tiny pinhole camera.
- Pip: 7 heads tall, tapered streamline body, faceted lacquer planes; silhouette marks: tilted pillbox cap + chin strap, a V of brass buttons, the sealed letter always in hand.
- Other props: the OUT OF ORDER plaque, the tower clock, the bulb sign THE STARLIGHT, the conductor and the score, waiters with silver trays, 8 dancers with emerald fans, fireworks.
Titles & end card
- Subtitle card speaker icons: a gold ribbon mic for the announcer, a burgundy pillbox cap for the hero.
- Title: MIDNIGHT / AT THE STARLIGHT HOTEL in a gold title bar over the stepped arch, a 1930 diamond year badge, NEW YEAR'S EVE label.
- End card: a lacquer plaque on the closed elevator doors: title, ART DECO, LEMO-OPUSCAR, "LemoLab × Claude Opus 5.5", asset credits. This sign-off belongs to this library's demo only; a user's film carries no LemoLab credit and no copy of this card.
Build notes
styles/art-deco/demo/
timeline.js tempo grid + all sync points (single source of truth) → tools/dump_timeline.mjs → timeline.json
engine/ deco.js (palette, gold, gline, airbrush, motifs, drawShape) · type.js (title bar, digits, badges, dial, clock, subtitle card)
bulbs.js (any text → bulb sign, lighting patterns) · cam.js (pinhole camera + card transforms)
chars.js Pip (FK rig, 4 views, 8 faces, pose library, run cycles), conductor, waiters, dancers, the letter
scenes/ lobby.js (one-point + mode-7 floor, doors, plaque) · roof.js (two-point sign) · tower.js · stairs.js
shots_*.js one function per shot: shot(g, t) film.js shot list, transitions (split / revolve / close), subtitles
frames.js model sheet, component kit, style frames, ?scene=frames.shotTest&shot=<name>
music/score.py original score → score.wav + stems + score.json mix.py voices in 5 spaces + foley + beds + ducking
tools/ cuecheck.py · subs.py · pitch.py · dump_timeline.mjs
- Write the tempo grid and the cue table first; hand them to a music sub-agent and draw in parallel.
- Build the engine and the hero model sheet, then one scene per location, then one function per shot. Review single shots with
?scene=frames.shotTest&shot=<name>. sh demo/build.shrebuilds everything: timeline → TTS → pitch → whisper → score → cue check → mix → srt → render (≈15 s with 4 workers for 1401 frames) → mux (−14 LUFS, grain 3) → stills.- Review at 1 s intervals with
still.mjs --range 0:58:1+sheet.py, then frame strips at 0.15–0.2 s for every key action.
Pitfalls tied to this demo's props:
- The first transition to the end card slid the elevator doors in over a flat brown "interior", which read as a blank frame; only the leaves are drawn now, closing over the live shot.
- The opening (one gold point on black) tripped
blackdetect; the background sunburst wedges and glow were lifted. - Pip at ¼ frame height in the bell shots was too small for the emotional peak; the last bell got a close-up.
- Three-digit hex turned the emerald fans blue-violet.
Engine reference
All drawing is Canvas2D, deterministic in t. Import from demo/engine/.
deco.js
| Function | Purpose |
|---|---|
C |
palette (ink black night gold0 gold1 gold2 goldHi ivory emerald burg plum skin bulb…) |
goldGrad(g, x0,y0,x1,y1, {sheen, hot, tint}) |
banded metal gradient; animate sheen −0.2→1.2 for a light sweep |
gline(g, pts, {w, part, closed, glow, double, sheen, alpha, color}) |
the engraved gold keyline; part 0→1 draws it on; color = any hex for the one-colour exception |
| `airbrush(g, pts | Path2D, {base, dark, light, dir, rim})` |
| `sunburst(g, cx, cy, {rays, r0, r1, mode:'lines' | 'wedges', a0, a1, rot, part})` |
stepArchPts(cx, base, w, h, {steps, crown}) / archFrame(g, cx, base, w, h, {rings, gap, fill, burst, part}) |
ziggurat arches and arch frames |
fan, fishScale, chevrons, sparkle, speedLines, glow, beam, vignette |
motif library |
drawShape(g, pts, {color, halo, trail, glints, part}) |
any path in the deco manner: airbrushed gold (or color) fill + gold keyline + optional sunburst halo, speed-line trail and glints |
starPts(cx, cy, r, k, rot, n) |
four-point star path |
type.js: goldText(g, text, x, y, {size, font, track, sheen}) · titleBar(g, text, cx, cy, {p, out, size, sub, wings}) (animated in/out) · decoDigits(g, '11:59', x, y, size) · yearBadge(g, '1930', cx, cy, r, {p}) · floorMedallion(g, '30', cx, cy, r, {sub}) · dial(g, cx, cy, r, value, {labels}) (semicircle floor indicator, value 0..1) · clockFace(g, cx, cy, r, {h, m, s, roman}) · subtitleCard(g, text, {p, out, speaker:'radio'|'boy'}).
bulbs.js: buildSign(text, {font, size, spacing}) (any text → glyph skeleton → evenly spaced bulbs, cached) · drawSign(g, sign, x, y, scale, {lit, channel, color}) · litAll(v) · litSequence(t, times[], {flash, chaseFrom, chaseSpeed}) (letter i switches on at times[i], then chases).
cam.js: makeCam({x, y, z, f, yaw, pitch, roll}) → {P(X,Y,Z), scaleAt(X,Y,Z)} · cardTransform(g, cam, TL, TR, BL, w, h) (map a flat card onto a 3D quad).
chars.js (demo characters): drawFigure(g, {x, y, s, view:'side'|'q'|'front'|'back', face, ...pose}) · POSES, FRONT_POSES, lerpPose, runCycle(phase), runFront(phase) · drawDancer, drawDancerTop, envelope, clef.
The one colour. To keep one element in its own colour, pass color — it is used for the fill, keyline and glow while everything else stays gold:
import * as D from './engine/deco.js';
import * as B from './engine/bulbs.js';
// a warm-orange four-point light with a short cursor tail, drawn the Art Deco way
D.sunburst(g, 960, 540, { rays: 72, r1: 1400, mode: 'wedges' });
D.drawShape(g, D.starPts(960, 540, 120, .22), { color: '#D97757', halo: 1, trail: { ang: Math.PI, len: 420, n: 4 } });
// a bulb sign that lights letter by letter, in the same orange
const sign = B.buildSign('LEMO', { size: 260, spacing: 20 });
B.drawSign(g, sign, 560, 700, 1, { lit: B.litSequence(t, [0, .5, 1, 1.5], { chaseFrom: 2.5 }), color: '#D97757' });




