# Gramophone horn

The acoustic deck a century before the electric one: a mainspring and its governor drive the platter, the crank is the wind, and the horn is an exponential flare modelled once and projected.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/gramophone-horn.json
```

Registry item: `gramophone-horn` · [`https://robocn.dev/r/gramophone-horn.json`](https://robocn.dev/r/gramophone-horn.json)

## Notes

- The governor is what makes a wind-up deck run at a speed at all. It holds the platter at its rate while the mainspring has torque to spare and lets it sag proportionally once it has not, and the flyweights stand out with the square of the speed until they reach their stop. Run it right down and the readout says so.
- It shares `turntable-deck`'s tonearm solver, which is how it can be honest about itself: a straight acoustic arm has almost no alignment geometry, so it never nulls and its tracking error is an order of magnitude worse than the electric deck's. The number is in the readout either way.
- The horn is an exponential flare — the cross-sectional area doubles over a constant distance along the axis — built as a stack of rings on one axis and projected, so it foreshortens truthfully from every camera instead of being drawn per angle.
- One approximation, stated: the platter's angle is the clock times the regulated speed, not an integral of it, so changing the wind changes the platter's rate from that moment rather than replaying history. There is no spring model, no torque curve and no acoustics — the mainspring's coil is a drawing.
- An original archetype. No manufacturer, product line, wordmark, paint scheme or record label is reproduced here or in the demo.

## Usage

```tsx
import { GramophoneHorn } from "@/components/ui/gramophone-horn"

<GramophoneHorn behavior="play" progress={0.4} />

// Controlled, or a crank you can wind by hand.
<GramophoneHorn wind={0.2} />
<GramophoneHorn interactive onWindChange={setWind} />
```

## Props

| name | type | default | description |
| --- | --- | --- | --- |
| `view` | `"plan" | "front" | "profile" | "iso"` | `"profile"` | Where the camera stands. One machine, four projections: straight down, straight on, side elevation, or three-quarter from above. |
| `wind` | `number` | — | Controlled wind, 0 run right down to 1 fully wound. Omit it and the spring runs behavior. |
| `behavior` | `"play" | "crank" | "static"` | `"play"` | Run the spring down over three quarters of the cycle and wind it back in the last quarter, or walk it up and down the range a hand on the handle covers. Static parks it wound and still. |
| `progress` | `number` | `0.3` | Where the soundbox is standing, 0 lead-in to 1 run-out. |
| `speed` | `number` | `0.1` | Cycles of the spring per second. |
| `animate` | `boolean` | `true` | Off parks the machine at phase and stops rendering. A reduced-motion preference does the same. |
| `paused` | `boolean` | `false` | Freeze where it stands. |
| `phase` | `number` | `0` | Seconds of offset, so a row of machines breaks step. |
| `interactive` | `boolean` | `false` | Drag round the crank to wind it — three turns of the handle is a full wind — or arrow-key it. |
| `onWindChange` | `(wind: number) => void` | — | How wound the spring is throughout a drag or a key press. |
| `showMechanism` | `boolean` | `true` | Show the spring barrel and the governor through the case's side panel. |
| `label` | `string` | — | Caption below the state readout. |
| `variant` | `"solid" | "outline" | "blueprint" | "wire"` | `"solid"` | How the machine is painted. Geometry never changes between variants. |
| `size` | `"xs" | "sm" | "md" | "lg" | "xl" | number` | `"md"` | Rendered width in pixels, or a step on the scale. |
| `color` | `string` | `var(--robot-shell)` | Body panels — the colour the machine reads as. |
| `accent` | `string` | `var(--robot-accent)` | Status colour: tip light, live tool, readouts. |
| `metal` | `string` | `var(--robot-metal)` | Bare machined parts: collars, bolts, tool bodies. |
| `dark` | `string` | `var(--robot-dark)` | Cast joints, base, shadow side. |
| `palette` | `Partial<RobotPalette>` | — | Override any subset of roles at once, including glow and grid. |

## Source

- `src/components/ui/gramophone-horn.tsx`
