# ロープ — Style Reference
> 骨色の紙に、麻の縄が一本垂れて床に溜まっている

**Theme:** light  **Series:** PARTS 045  **World:** 架空の縄製造所「Nawa」のトップ。製品の縄を1本だけ吊るし、重さと摩擦の挙動で素材を見せる。

## Concept
画面の中央やや右に吊り金具があり、そこから麻色の縄が1本垂れている。縄は床(画面下部の細い線)まで届き、余った分が床に横たわる。起動時は左へ振り上げた状態から落ち、振り子のように揺れて収まる。つかんで引くと縄全体が付いてきて、離すと床の摩擦で止まる。文字は床の下に、細いセリフで見出し1行と本文2文。

## Signature Technique
Verlet 積分のロープ + 距離拘束 + 曲げ剛性 + 床の摩擦。2D canvas で描く。

1. **質点**: `n`(70、モバイル 56)個。`{x, y, px, py}` を持ち、`pts[0]` は吊り点に固定。区間長 `L = floorY·lengthK / (n−1)`(lengthK 1.3、モバイル 1.16)。
2. **積分**(1 フレームに 4 ステップ、`dt = frame/4`):
   ```js
   vx = (x − px)·drag;  vy = (y − py)·drag;          // 空気抵抗 0.997/ステップ
   if (y >= floorY) vx *= friction;                   // 床に触れている質点は横速度が 0.45 倍
   px = x; py = y;  x += vx;  y += vy + g·dt²;         // 重力 2600 px/s²
   ```
3. **拘束**(18 反復): 隣接点の距離を L に戻す(吊り点側は動かさない)。2 つ先の点との距離が `2L·0.97` を下回ったら押し広げる(曲げ剛性)。床より下に出たら `y = floorY`、左右は画面端から縄の太さ w(56px / モバイル 34px)の位置が壁。つかんでいる点は毎反復 60% の割合でカーソルへ寄せる。
4. **描画**: Catmull-Rom で質点 1 区間を 6 分割して滑らかな折れ線にし、次の順で重ねる。
   - 床: 床の線から下へ `rgba(120,104,72,.10)`→0 の縦グラデーション。
   - 影: `blur(0.22w)` の `rgba(40,30,10,.17)`、幅 1.05w、右下へ (0.55w, 0.8w) ずらす。
   - 胴は別キャンバス(同サイズ)に描く: 暗い縁 `#5e4729` 幅 w → 地 `#9a7d4e` 幅 0.8w → 光 `#b39566` 幅 0.5w を左上へ 0.08w。
   - 撚り(3 本撚り): `globalCompositeOperation = 'source-atop'` で胴の形に切り抜き、弧長 `twist`(0.6w)ごとに、法線方向へ ±0.62w、進行方向へ 0.62 傾けた溝を引く(幅 0.3w の `rgba(52,36,14,.30)` の上に幅 0.07w の `rgba(40,26,8,.72)`)。溝の半ピッチ先に、光の側(左上)寄りの子縄の膨らみ(幅 0.17w `rgba(236,214,166,.55)` + 芯の白 0.05w)と、溝に平行な繊維線3本(1px)。最後に光の側へ blur した明るい帯を重ね、本キャンバスへ drawImage。
   - 毛羽: 胴の外側に、弧長 4px ごとに半数の確率で長さ 0.06–0.26w の細い曲線(0.7px、`rgba(150,120,74,.42)`)。乱数は `sin` ハッシュで固定し、毎フレーム同じ位置に生える。
   - 結び目: 止め結び。胴の膨らみ(放射グラデーション)→巻き付く斜めの筋→脇に出た輪、の順に重ねる(輪が手前)。輪にも胴と同じ撚りの溝を 15 本、接線に対して 0.95 の傾きで刻み、溝ごとに明るい膨らみの線を添える。弧長 0.38 の位置。影は縄の向きで回さず、画面の右下 (0.55w, 0.8w) に `blur(0.2w)` の `rgba(40,30,10,.2)` で落とす(光は左上で固定)。
   - 末端: 先端から 1.6w 手前に、暗い糸の巻き(ホイッピング、`#3b2e1c` の 0.9w×w に明るい縦線6本)と、細い繊維 15 本のほつれ。
   - 吊り元: 天井の金属座金(2.5w×0.42w、ボルト2本)→アイボルト→シャックル→縄の端を折り返したアイ(輪、撚りの斜線14本)→根元を締める糸巻き。吊り点は `y = 2.95w`。
5. **停止条件**: 質点あたりの移動量が 0.02px 未満の状態が 90 フレーム続いたら rAF を止める。つかむと再開。IntersectionObserver と visibilitychange で画面外停止。

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --bone | #fcf9ee | 地 |
| --linen | #f2efe3 | 予備の面(未使用) |
| --pebble | #bcbab2 | 床の線、ヘッダーのラベル、操作説明 |
| --bark | #6a6965 | 本文 |
| --ink | #1a1916 | 見出し、ブランド名、クレジット |
| steel(canvas) | #2b2b2d → #d4d4d8 | 金具。横方向の金属グラデーション(暗→明→暗) |
| --hemp | #b89b6a | CSS 側の麻色(予備。canvas では使っていない) |
| hemp(canvas) | #9a7d4e | 縄の地の色。縁は #5e4729、光は #b39566、子縄の膨らみは rgba(236,214,166,.55)、溝は rgba(40,26,8,.72) |

## Typography
- ブランド名と見出し: Newsreader 300(opsz 6–72)、見出し `clamp(28px, 2.6vw, 38px)`、letter-spacing −0.01em、line-height 1.3。日本語は Noto Serif JP 300 にフォールバック。
- 本文: Noto Serif JP 300、`clamp(13px, 1.05vw, 15px)`、line-height 1.8、最大幅 30em。2文目を `inline-block` の span で包み、文の途中(「止ま/り」)で折り返さないようにする。質点数は JS で書き込む。
- ラベル: JetBrains Mono 400、11–12px、letter-spacing 0.06–0.08em。
- canvas 不可時は `.fallback` にブランド名を Newsreader 300 で出す。

## Spacing & Layout
- hero `min-height: 100svh`、3行グリッド。canvas は背面全面(`touch-action: none`、`cursor: grab`)。
- 余白: 横 `clamp(20px, 5vw, 72px)`、上 `clamp(20px, 3vw, 40px)`、下 `clamp(18px, 2.6vw, 32px)`。モバイル左右 18px。
- 床は `H − 205px`(モバイル `H − 250px`)。文字はすべて床の線より下に置く。吊り点は `x = 0.6W`(モバイル 0.62W)、`y = 2.95w`(上に金具が入る)。
- 縄の太さ 56px(モバイル 34px)。画面の主役として、細い線に見えない太さにする。
- breakpoint 760px: ブランド横の説明と右上のラベルを消し(金具と重なるため)、フッターを縦積み。

## Motion
- 起動: 左へ最大 0.62 rad(画面幅に収まる角度まで)振り上げた状態から落とす。モバイルは真下から始める(狭い画面では縄が折れて輪になる)。揺れは 5–8 秒で収まる。
- つかむ: 半径 48px 以内の質点をつかみ、ポインタに追従。`setPointerCapture` で canvas 外に出ても離れない。
- 床の摩擦 0.45、空気抵抗 0.997/ステップ、曲げ剛性 0.97。
- `prefers-reduced-motion: reduce`: 真下に垂らした状態で 600 ステップ進め、静止した縄を1枚描く。つかむ操作は動く。

## Components
- hero: 背面 canvas + 前面テキスト。テキスト層は `pointer-events: none`。
- header: 左にブランド名(セリフ 17px)、右に `70 points · hemp 32 mm`。
- copy: 見出し1行+本文2文。床の線の下。
- footer tag: `VALE / PARTS 045 / ロープ` と操作説明1行(タッチ端末では文言差し替え)。

## Do / Don't
- Do: 撚りの線は弧長基準で等間隔に打つ。質点基準だと伸び縮みで間隔が揺れる。
- Do: 曲げ剛性を入れる。無いと縄が糸のように折れ、床で団子になる。
- Do: 床の線を細く1本だけ引き、文字はその下に置く。縄と文字が重ならない。
- Do: 撚りと毛羽は source-atop で胴の形に切り抜く。溝が縁からはみ出すと縞模様の帯に見える。
- Don't: 縄を 2 本以上吊らない。主役が散る。
- Don't: 影を濃くしない(alpha 0.2 以上)。紙の上の縄に見えなくなる。
- Don't: 反復回数を 10 未満にしない。縄が伸びてゴムになる。

## References
- Spécialiste Belge: 骨色の紙に黒い文字、装飾は紙の縁だけという構成を借りた。紙の縁を床の線に置き換え、素材(縄)を1つだけ置いた。
- Steep: 暖かい紙の上に軽いセリフ見出しを置き、本文は小さく静かにする階層を借りた。グラフの代わりに物理の縄を主役にした。

## Usage
1. `<canvas id="c">` を hero の背面に置き、Newsreader と Noto Serif JP を `<link>` で読み込む(書体は任意)。
2. `<script>` ブロック全体を移植する。`document.fonts.ready` 後に `boot()` が走る。
3. 床の高さは `resize()` の `floorY`。文字の高さに合わせて `H − 205` を変える。
4. 縄の色は `draw()` 内の胴3色と撚りの溝・膨らみの色を差し替える。太さは `P.width`、撚りのピッチは `P.twist`(太さの 0.6 倍前後)。金具が不要なら `fitting()` の呼び出しを消し、`ay` を小さくする。
5. 両端を吊るしたい場合は `pts[n−1]` も拘束ループで固定する(`pts[0]` と同じ扱い)。

| パラメータ | 既定 | 意味 |
|---|---|---|
| n | 70 / 56(モバイル) | 質点の数 |
| lengthK | 1.3 / 1.16(モバイル) | 縄の長さ(床までの高さに対する比)。1 を超えた分が床に溜まる |
| width | 56 / 34(モバイル) | 縄の太さ(px)。左右の壁の幅も兼ねる |
| knotAt | 0.38 | 結び目の位置(縄の弧長に対する比) |
| gravity | 2600 | 重力(px/s²) |
| drag | 0.997 | 空気抵抗(毎ステップの速度残存率) |
| friction | 0.45 | 床の摩擦(横速度の残存率) |
| iters | 18 | 拘束の反復回数 |
| bend | 0.97 | 曲げ剛性(2 つ先との最小距離の係数) |
| grabR | 48 | つかめる距離(px) |
| anchorX | 0.6 / 0.62(モバイル) | 吊り点の横位置(幅に対する比) |
| twist | 34 / 21(モバイル) | 撚りの間隔(px) |

質点を 200 以上にする場合は `iters` を 30 に上げるか、拘束を Gauss-Seidel のまま両方向から交互に解く。
