# なめらかな追従 — Style Reference
> クリーム色の紙に黒い大文字のポスター。カーソルの代わりに黒い塊が遅れてついてきて、文字の上で白く反転する

**Theme:** light  **Series:** PARTS 052  **World:** 架空の「あとで読む」サービス「Ato」のトップ。保存する気軽さを、遅れてついてくる塊の柔らかさで示す。

## Concept
カーソルを隠し、代わりに6つの円を置く。先頭はカーソルに硬いばねで、2つ目以降は前の円に少しずつ柔らかいばねでつながるので、速く動かすと尾を引き、止まるとひとつの塊に戻る。円は SVG フィルタでメタボールとしてつながり、`mix-blend-mode: difference` で重ねるので、紙の上では黒、黒い文字の上では白、黄色の帯の上では青になる。装飾は黄色の帯1本だけ。

## Signature Technique
DOM + SVG フィルタ + ばねの鎖。ライブラリなし。

- **塊**: 直径 56 / 46 / 38 / 30 / 24 / 18px の白い円(`.b`)。`.goo` に `filter: url(#goo)`、その親 `.blobs` に `mix-blend-mode: difference`。白との差なので、下地の色がそのまま反転する。
- **goo フィルタ**: `feGaussianBlur stdDeviation=9` → `feColorMatrix` でアルファを `22·a − 10` に引き伸ばす → `feComposite operator=atop` で元の円を重ねる。近づいた円の間に橋ができる。
- **ばねの鎖**: 先頭の目標はカーソル、i 番目の目標は i−1 番目の位置。`a = (target − x)·k − v·c`、k = 220 → 90、c = 22 → 12。dt は 33ms 上限。
- **hover**: `[data-hover]` の上では先頭の円を 2.2 倍にする(15%/フレームで補間)。goo で後続と一体になる。
- **無操作時**: 黄色の帯 `.band` の矩形を基準に、2行の見出しの上をリサージュ(0.22 rad/s、縦は 1.7 倍)で巡回。初期位置もそこ。
- `.hero` に `background` と `isolation: isolate` を与え、difference の下地を確保する(下地が透明だと白いままになる)。
- `id` の重複に注意: フィルタの id とレイヤーの id は別名にする。

```js
for (let i = 0; i < N; i++) {
  const b = blobs[i], tx = i ? blobs[i-1].x : t.x, ty = i ? blobs[i-1].y : t.y;
  b.vx += ((tx - b.x) * k[i] - b.vx * damp[i]) * dt; b.vy += ((ty - b.y) * k[i] - b.vy * damp[i]) * dt;
  b.x += b.vx * dt; b.y += b.vy * dt;
  b.el.style.transform = `translate(${b.x - size[i]/2}px, ${b.y - size[i]/2}px) scale(${b.s})`;
}
```

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --paper | #fbf9f2 | 紙。hero の背景にも同じ値 |
| --ink | #0d0d0d | 見出しと本文とボタン枠 |
| --butter | #fbda5f | 見出し2行目の帯。画面で唯一の色 |
| --fog | #8e8d88 | 本文補助とヘッダー補助とメタ情報 |
| 塊 | #ffffff を difference | 紙の上で #04060d、黒の上で白、黄の上で #0425a0 |
| --stone | #e5e4e3 | 予備の面 |

## Typography
- 見出し: Phudu 700、`clamp(56px, 11.6vw, 176px)`(モバイル 17vw、上限 120px)、line-height 0.9、letter-spacing −0.01em の大文字2行。2行目を黄色の帯で囲む。
- 日本語見出し: Noto Sans JP 500、`clamp(17px, 1.5vw, 21px)`、line-height 1.5、letter-spacing 0.01em、最大幅 26em。本文 400、`clamp(13px, 1.05vw, 15px)`、最大幅 26em。
- ボタン: Noto Sans JP 500 14px、letter-spacing 0.02em、padding 12px 22px、1.5px の枠、角丸 999px。
- ラベル: JetBrains Mono 400、11–12px、letter-spacing 0.06em。

## Spacing & Layout
- hero `min-height: 100svh`、3行グリッド。見出しは中央行の左、下に日本語見出し・本文・ボタンを横並び(モバイルは縦)。
- 余白: 横 `clamp(20px, 5vw, 72px)`、上 `clamp(20px, 3vw, 40px)`、下 `clamp(18px, 2.6vw, 32px)`。モバイル左右 18px。
- コピー行は見出しの下 `clamp(20px, 3vw, 40px)`、要素間 `clamp(20px, 4vw, 56px)`。
- `.blobs` は hero 全面(`inset: 0`)、`pointer-events: none`、z-index 2。
- breakpoint 760px: ヘッダー右とメタ情報を消し、見出しを `clamp(56px, 17vw, 120px)` に、コピー行を縦積み(間隔 16px)、フッターを縦積み。

## Motion
- 先頭は約 0.1 秒でカーソルに追いつき、最後尾は約 0.4 秒遅れる。止まると 0.5 秒ほどで1つにまとまる。
- 無操作時・タッチ端末では見出しの上を周回。
- rAF 1本。IntersectionObserver と visibilitychange で画面外停止。
- `prefers-reduced-motion: reduce`: 起動時に 90 ステップ分を先に計算し、帯の上に静止したひと塊を置く。連続アニメーションはせず、カーソル移動時はイベントごとに1ステップだけ進める。
- `@media (hover: hover)` のときだけ `cursor: none`。

## Components
- hero: 紙の背景+ポスター型の見出し+コピー+ボタン+塊のレイヤー。
- header: 左にサービス名、右に技法名。
- button: 「記事を保存する」。`data-hover` で塊が広がる。`focus-visible` に 2px の黒いアウトライン。
- meta: 左下に塊の数とばねの硬さとぼかし量。
- footer tag: `VALE / PARTS 052 / なめらかな追従` と操作説明1行(タッチ端末では差し替え)。

## Do / Don't
- Do: 塊の色は白1色にして difference に任せる。下地が何色でも成立する。
- Do: ばねは先頭を硬く、後ろを柔らかく。全部同じだと鎖に見えない。
- Do: 下地になる要素に背景色を必ず付ける。
- Don't: 円を 8 個より増やさない。尾が長すぎると虫に見える。
- Don't: ぼかしを 14px 以上にしない。輪郭が溶けて汚れに見える。
- Don't: 塊に影やグラデーションを足さない。

## References
- SaveDay: クリーム色の紙に特大の黒い大文字を組み、黄色の帯を1本だけ引くポスターの型を借りた。帯を2行目の背景に絞り、他の色は使わない。
- Dyotanya: 暖かい紙の上で、手描きの線のような柔らかい要素が文字の間を漂う空気を借りた。線の代わりに塊を置き、文字の上で反転させた。

## Usage
1. `<svg class="defs">` の `#goo` フィルタと、`.blobs > .goo` のレイヤー、`.b` の CSS を移植する。
2. `<script>` ブロック全体を移植する。塊を広げたい要素に `data-hover` を付ける。
3. 下地の要素(hero)に `background` と `isolation: isolate` を付ける。
4. 色を変えるときは `.b` の背景色を変える(白以外にすると反転の色が変わる)。
5. 無操作時の周回範囲は `idle()` 内の `.band` を別の要素に差し替える。

| パラメータ | 既定 | 意味 |
|---|---|---|
| sizes | 56 / 46 / 38 / 30 / 24 / 18 | 円の直径(px)、先頭から |
| k | 220 → 90 | ばねの硬さ、先頭から |
| damp | 22 → 12 | 減衰 |
| hoverScale | 2.2 | `data-hover` 上での先頭の拡大 |
| idleSpeed | 0.22 | 無操作時の周回速度(rad/s) |
| stdDeviation | 9 | goo のぼかし量(px) |
