# 波紋 — Style Reference
> 夜の池。水底に沈んだ白い一文字が、波紋でゆらぐ

**Theme:** dark  **Series:** PARTS 048  **World:** 架空の池の記録サービス「Minamo」のトップ。水面を数値で語る代わりに、水面そのものを画面にする。

## Concept
画面全体が暗い水面で、水底に「水」の一文字が沈んでいる。数秒おきに雫が落ちて波紋が広がり、文字は波紋の法線に沿って屈折してゆらぐ。波の斜面には空の色が薄く映り、頂点には小さな光が走る。クリックで大きな波紋、カーソルでなでると細かい波が立つ。文字は左下に見出し 1 行と本文 2 文。

## Signature Technique
波動方程式の高さ場(GPU)+ 法線による屈折と反射。

1. **高さ場**: 横 `simW`(512、モバイル 256)、縦は aspect から決める RGBA float テクスチャ 2 枚をピンポン(`OES_texture_float_linear` があれば LINEAR で補間)。`r` = 現在の高さ、`g` = 1 ステップ前の高さ。
2. **波動方程式**(`WAVE_FS`、1 フレームに 2 回):
   ```glsl
   float lap = h(l)+h(r)+h(d)+h(u) − 4h;
   float next = (2h − h_prev + c²·lap) · damp;     // c 0.40、damp 0.991
   next −= amp · smoothstep(R, 0, r) · (1 − .4·smoothstep(0, R/2, r));   // 雫: 半径 R の窪み(中心をやや深く)。r は aspect 補正した距離
   edge: 外周 1 texel は 0 に固定(固定端)
   ```
   雫はキューに積み、1 サブステップに 1 つずつ注入する。
3. **表示**(`SHOW_FS`):
   - 勾配 `g = (h(r) − h(l), h(u) − h(d)) / 2`、法線 `n = normalize(−7g, 1)`。
   - 屈折: 水底テクスチャを `uv + n.xy · 0.05` で引く。
   - 深さ: 画面中心からの距離で水底を暗くする(`deep #0b1a22`、周辺は 0.6 倍)。
   - フレネル: `(1 − n·V)³ · sky(#2a3340) · 0.9`。
   - ハイライト: Blinn-Phong `pow(n·H, 120) · 0.55`、色は白と lime(#e4f222)の 6:4。光は左上奥 `(−0.35, 0.5, 0.8)`。
   - コースティクス風: ラプラシアンの負の部分で水底を明るくする(`clamp(−3·lap, −0.1, 0.2)`)。
4. **水底テクスチャ**: 2D canvas に黒地で Noto Sans JP 900 の一文字(#e8ecf2)を描き、LINEAR の RGBA8 テクスチャに転送。文字の大きさは `min(高さ × 0.58, 幅 × 0.5)`。テクスチャ幅は最大 1600px。
5. **雫**: 自動で 1.4–2.8 秒おきに x 0.15–0.85、y 0.2–0.8 の範囲へ(半径 0.7–1.3 倍、高さ 0.6–1.2 倍)。クリックは半径 1.4 倍・高さ 1.6 倍。カーソル移動は 0.004 以上動くたびに半径 0.025・高さ 0.06 の小さな窪み。
6. 起動時に 3 滴を落として 66 ステップ進め、最初から波紋がある状態で見せる。IntersectionObserver と visibilitychange で画面外停止。リサイズで高さ場と水底を作り直す。

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --void | #08090a | 地(canvas の外) |
| (deep) | #0b1a22 | 水の色。中心が最も明るく、周辺へ 0.6 倍 |
| (sky) | #2a3340 | 波の斜面に映る空 |
| (bed) | #e8ecf2 | 水底の文字 |
| --mist | #d0d6e0 | 本文 |
| --fog | #8a8f98 | ヘッダーのラベル、操作説明 |
| --paper | #ffffff | 見出し、ブランド名、クレジット |
| --lime | #e4f222 | ハイライトの色味(白と 6:4)、読み出しの区切り点 |

## Typography
- ブランド名: Inter 500、15px、letter-spacing −0.01em。
- 水底の文字: Noto Sans JP 900 の一文字。細い書体は屈折で切れる。
- 日本語見出し: Noto Sans JP 400、`clamp(20px, 1.8vw, 26px)`、letter-spacing −0.01em、line-height 1.45。
- 本文: Noto Sans JP 300、`clamp(13px, 1.05vw, 15px)`、最大幅 30em。本文は文節ごとに `white-space:nowrap` の span(`.nw`)で包み、改行は文節の境目だけで起きる(デスクトップの「屈折さ/せている」、スマホの「文/字」の語中改行を防ぐ)。
- ラベル: JetBrains Mono 400、11–12px、letter-spacing 0.06–0.08em。格子の寸法は JS で実測。
- WebGL 不可時は `.fallback` に同じ一文字を HTML で表示。

## Spacing & Layout
- hero `min-height: 100svh`、3行グリッド。canvas は背面全面(`cursor: crosshair`)。
- 余白: 横 `clamp(20px, 5vw, 72px)`、上 `clamp(20px, 3vw, 40px)`、下 `clamp(18px, 2.6vw, 32px)`。モバイル左右 18px。
- 水底の文字は高さの 47%(縦長では 40%)を中心に置き、左下のテキストと重ねない。
- breakpoint 760px: ブランド横の説明を消し、フッターを縦積み。

## Motion
- 波の速さ c = 0.40 格子/ステップ、120 ステップ/秒。512 格子を横切るのに約 2 秒。
- 減衰 0.991/ステップ。波紋は約 4 秒で消える。
- 自動の雫 1.4–2.8 秒おき(最初は 0.6 秒後)。
- `prefers-reduced-motion: reduce`: rAF を回さず、起動時の 3 滴 66 ステップの状態を 1 枚描いて止める。クリックやなでる操作では、そのたびに 1 フレームだけ進む(自走しない)。

## Components
- hero: 背面 canvas + 前面テキスト。テキスト層は `pointer-events: none`。
- header: 左にブランド名、右に `grid 512×320 · c 0.40`。
- copy: 見出し 1 行+本文 2 文。
- footer tag: `VALE / PARTS 048 / 波紋` と操作説明 1 行(タッチ端末では文言差し替え)。

## Do / Don't
- Do: 雫の半径は格子の 2% 以上にする。小さいと高周波が立ち、縞模様になる。
- Do: 法線の倍率は 5–8。大きくすると屈折が暴れて文字が読めない。
- Do: 水底には 1 文字だけ。文章を沈めると屈折で読めず、意味も薄れる。
- Don't: 減衰を 0.995 以上にしない。波紋が消えず、画面が常に揺れて文字が読めない。
- Don't: ハイライトを純色のライムにしない。白を混ぜると光、純色だと蛍光ペンになる。
- Don't: 水面に粒子や泡を足さない。法線の屈折だけで水に見える。

## References
- Linear: ほぼ黒の面に白い文字、acid lime を 1 点だけという配色を借りた。lime をボタンから水面のハイライトに移した。
- Rou Hun Fan: 黒い紙に版画のような 1 色のインクを置く考え方を借りた。インクの代わりに水底の 1 文字を置き、屈折でにじませた。

## Usage
1. `<canvas id="gl">` を hero の背面に置き、Noto Sans JP 900(または任意の太い書体)を読み込む。
2. `<script>` ブロック全体を移植する。`document.fonts.load` 後に `boot()` が走る。
3. 水底を差し替える: `makeBed()` の中身を任意の描画(ロゴ、画像)にする。画像なら `drawImage` して転送する。
4. 色は `deep` / `sky` / `lime` と水底の文字色を CSS 変数と揃える。
5. 自動の雫が不要なら `P.rainEvery` を `[1e9, 1e9]` にする。

| パラメータ | 既定 | 意味 |
|---|---|---|
| simW | 512 / 256(モバイル) | 高さ場の横解像度。縦は aspect から |
| c / damp | 0.40 / 0.991 | 波の速さ(格子/ステップ)と減衰 |
| sub | 2 | 1 フレームの積分回数 |
| dropR / dropAmp | 0.022 / 0.45 | 雫の半径(高さ比)と高さ |
| rainEvery | [1.4, 2.8] | 自動の雫の間隔(秒) |
| touchR / touchAmp | 0.025 / 0.06 | カーソルでなでる半径と高さ |
| refract / spec | 0.05 / 0.55 | 屈折の強さとハイライトの強さ |
| word | 水 | 水底の文字 |
| dprMax | 2 | 表示解像度の上限 |

c は 0.5 未満にする(CFL 条件 c² ≤ 0.5)。超えると発散する。
