# 鋼の関節 — Style Reference
> a single machined elbow joint under cold studio light, taken apart one part at a time while an orange HUD reticle follows the piece being explained.

**Theme:** dark  **Series:** EDGE 001  **World:** 巨大機体の肘関節ユニット KX-7 を分解図で見せる。

## Concept
One product, one object. The page is a spec sheet for a fictional elbow joint unit. The 3D assembly is the hero and stays fixed behind every section; scrolling is the only control. Each section explains one part (pistons, reduction gear, main shaft) and the assembly explodes further as the reader moves down, then switches to a wireframe drawing, then reassembles behind the request form. The HUD reticle (SVG) tracks the part named in the current section, so the eye always lands on the thing the sentence talks about. Nothing in the page is decoration: gear teeth, bolt rings and the orange stripe on the piston rod are all part of the machine.

## Signature Technique
Three.js r170, one WebGLRenderer, one requestAnimationFrame.

- **Procedural parts.** No model files. Housings are `LatheGeometry` from a 7 point profile (chamfered ring), the gear is an `ExtrudeGeometry` from a Shape with 32 trapezoid teeth and a bored hub, fork plates are an extruded arc + taper Shape with two holes, pistons are stacked cylinders oriented with `Quaternion.setFromUnitVectors`. Segment count 96 on desktop, 48 on mobile.
- **Procedural environment.** `PMREMGenerator.fromScene` on a small scene: a dark box, one wide softbox overhead (color x6), two cool vertical strips, one orange strip low behind (0xff6b1a x7), a front fill card. The orange rim light on the dark housings comes only from this strip; there is no orange light in the main scene.
- **Metal.** `MeshStandardMaterial`, metalness 1, roughness 0.30 (steel) / 0.55 (dark) / 0.18 (chrome), `envMapIntensity` 1.1 to 1.4. The roughness map is a 512px canvas with about 2600 horizontal 1px strokes at random gray, so every lathe surface reads as brushed. ACES tone mapping, exposure 1.05. The procedural PMREM room has a window of four tall narrow panes (0.45 x 7, intensity 20) at the front left, so the brushed steel shows sharp window bands in a still image.
- **Framing.** When exploded, the camera pulls back by `6.8 * E` on wide screens (7.5 on portrait) and the rig drops by `0.45 * E`, so the upper-arm bridge and the lower arm both stay inside a 1440 x 900 frame.
- **Explode.** Every part has `base`, `dir`, `dist`, `t0`, `t1`. Position = base + dir * dist * ease(smoothstep(t0, t1, E)), where E is the global explode value from scroll. Shells (fork, bridge, lower arm) leave first (t0 0.0 to 0.1), pistons next (0.25), housings and bearings (0.45 to 0.55), gear and cover last (0.55 to 0.6). This stagger is what makes it read as a drawing and not a blast.
- **Scroll mapping.** Six keyframes, one per section: `{ry, rx, ex, wire, px, focus}`. Scroll position is converted to a continuous index s from the sections' offsetTop; between keyframes the blend is `smoothstep(0.2, 0.8, frac)` so each state holds still for the first and last fifth of a section while the copy is read. All values pass through an exponential lerp (`1 - exp(-6 dt)`) so a fast scroll never snaps.
- **Wireframe.** Each mesh carries an `EdgesGeometry(geo, 24)` LineSegments twin. The wire value fades metal opacity to 0.06, turns `depthWrite` off so hidden lines show, and fades lines in (gray 0x9aa3ad, orange for the marked rings).
- **HUD.** A full screen SVG. Each frame the focus object's `Box3` corners are projected with `Vector3.project(camera)`, the screen rect is clamped inside a 64px margin, and the bracket, crosshair, leader and label are lerped toward it. Labels flip to the left side of the bracket when the right side would leave the viewport.
- **Mobile.** Pixel ratio capped at 1.5, no antialias, camera pulled back 7.5 units during explode so the spread stays inside the portrait frame, model centred in the upper half, copy at the bottom over a gradient.
- **Reduced motion.** No idle wobble, no pointer parallax, lerps snap to target. Scroll still sets the state.

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --bg | #0b0c0e | page canvas, body background |
| --bg-2 | #141619 | radial centre behind the model |
| --panel | #1b1e22 | fallback box surface |
| --steel | #8e959c | HUD readouts, mono captions |
| --steel-2 | #5b6168 | HUD frame corners, footer text |
| --text | #e9ebee | headings, HUD part names |
| --text-2 | #aab0b7 | body copy |
| --orange | #ff6b1a | reticle, eyebrow, button border, painted rings in the 3D |
| --orange-2 | #c24d0e | reserved darker orange for pressed states |
| metal steel / dark / chrome | #c3c8ce / #5e656c / #e6e9ec | MeshStandardMaterial base colors |

Orange appears in four places only: HUD, eyebrow rule, button, and the painted rings inside the machine. Everything else is gray.

## Typography
- **IBM Plex Sans JP** 200 / 300 / 400 / 500. Display h1 at clamp(56px, 8.6vw, 124px), weight 200, line-height 1.02, letter-spacing 0.06em. Section h2 clamp(32px, 3.6vw, 52px), weight 200, letter-spacing 0.05em. Body clamp(15px, 1.15vw, 17px), weight 300, line-height 1.7, max 40ch.
- **IBM Plex Mono** 400 / 500 for everything that behaves like an instrument readout: eyebrow codes (11px, 0.18em, uppercase), code tags (11px, 0.16em), HUD (11px, 0.08em), header and footer.
- Japanese is primary. English stays at label length (part codes, "Spur Gear", "SCROLL").
- The thin display weight on a near black canvas is the quiet move: the machine is heavy, the type is not.

## Spacing & Layout
- Base unit 4px. Gutter `clamp(20px, 8vw, 120px)` on both sides.
- Each section is `min-height: 100svh`, flex, vertically centred. Copy column max-width 520px. Sections alternate left / right (`.right`), and the model moves to the opposite side via the `px` keyframe (+2.2 / -2.9 world units).
- Header and footer are the only chrome: fixed header with two mono labels, footer with a hairline top border.
- Breakpoint 760px: copy drops to the bottom of the viewport with a dark gradient behind it, h1 clamp(56px, 17vw, 80px), both alternating sections align left, scroll hint hidden.

## Motion
- Everything is driven from scroll through the keyframe table; nothing autoplays except a 0.05 rad idle sway (sin t * 0.35) and a 0.06 unit piston breathing when assembled.
- Pointer parallax on desktop only: rotation offset 0.08 rad vertical, 0.14 rad horizontal, lerped.
- Camera dolly: 16.5 units base on desktop (scaled up for narrow aspect), plus 2.6 units during explode; portrait 22.5 base plus 7.5.
- Over the last section the joint reassembles (explode 0) and the canvas and HUD fade to 65% on wide screens (15% on portrait). On wide screens the brushed steel photo is masked to the left (`mask-image: linear-gradient(90deg, #000 30%, transparent 62%)`), so the closing screen pairs the request copy with the finished joint on the right.
- Button hover: background fills orange, text turns to the page black, 250ms ease.
- `prefers-reduced-motion`: sway, breathing, parallax and lerps off; scroll hint animation off. The page still reads as a static exploded drawing at any scroll position.

## Components
- **hero**: full viewport; eyebrow, h1, one sentence, scroll hint bottom-left; assembled model right of centre with the reticle on the hub labelled `KX-7 / 関節ユニット`.
- **section**: eyebrow with part code, h2, one or two sentences, two mono code tags; model exploded to that section's value with the reticle on the named part.
- **wire section**: same copy block; metal fades, edge lines in.
- **button**: 1px orange border, transparent fill, 16/26px padding, 14px sans weight 400, 0.14em tracking, trailing 28px rule that grows to 40px on hover.
- **footer**: hairline top, two mono labels, `VALE / EDGE 001`.
- **fallback**: when WebGL fails, `html.nogl` hides canvas and HUD and shows a bordered text box under the hero copy.

## Do / Don't
Do
- Keep one object. Add detail to the machine, never a second machine.
- Let orange mean "this is what we are talking about" and nothing else.
- Hold the state still while text is on screen; move only between sections.
- Keep copy to one heading and one or two sentences per screen.

Don't
- No background grids, particles or floating shapes behind the model.
- No glow, bloom or lens flares on the orange.
- No photographic metal as the main surface; the image is a panel behind the form only.
- No text inside the 3D scene; labels live in the SVG HUD.

## References
- **SoundCloud** (stock/refero/md/soundcloud.md): near-black stage where one cool accent does all the work and the chrome stays invisible, plus a 100-weight display face at large size. Abstracted: single accent on near black, thin display type, flat squared controls. Changed: accent is a warning orange and lives in a 3D scene; the "content" that carries the color is a machine instead of album art; type is IBM Plex Sans JP instead of a geometric sans.
- **Limón** (stock/refero/md/lim-n.md): wide positive tracking that scales with size, one chromatic note on a dark room, candlelit warmth from a single light source. Abstracted: tracking 0.06em at display down to 0.05em at h2, one orange strip in the environment map playing the candle. Changed: dropped the cream breathing sections and the yellow; the palette is cold gray with one hot edge, and the warmth is reflected rather than painted.
