# カーボン — Style Reference
> 黒い作業場の壁一面が綾織りのカーボン。光を動かすと繊維が斜めに光る

**Theme:** dark  **Series:** PARTS 027  **World:** 架空の自転車フレーム工房「Tow」のトップ。素材そのものを背景にして、工房が開いていることを緑の点ひとつで示す。

## Concept
画面全体を 2/2 綾織りのカーボン繊維にする。繊維束(トウ)は画像を使わず、セル座標から織りの上下と繊維方向を計算して描く。カーソルの位置に点光源があり、繊維方向に沿った異方性のハイライトとクリアコートの鋭い反射が光源の周りだけで強くなるので、光を動かすと織り目の斜めの流れが浮かぶ。文字は左に寄せ、弱い黒のグラデーションで読みやすさを確保する。色は無彩色と緑の点だけ。

## Signature Technique
全画面1枚のフラグメントシェーダー(WebGL1)。手続きの綾織り + Kajiya-Kay 異方性 + クリアコート。

- **セル**: `uv = px / tow`(tow = 15px、モバイル 11px)、`cell = floor(uv)`、`f = fract(uv)`。
- **2/2 綾織り**: `m = (cell.x − cell.y) mod 4`。m ∈ {0,1} なら横糸が上、{2,3} なら縦糸が上。浮き(上に出ている区間)は2セル続くので、浮きの中の位置は `along = (m + f.x)/2`(横)または `((3 − m) + f.y)/2`(縦)。横切る座標 `across` は f のもう一方。
- **束の形**: 断面 `bulge = sin(π·across)`、浮きの両端で沈む `dip = smoothstep(0,.12,along)·smoothstep(0,.12,1−along)`。法線は断面の傾き `π cos(π·across)·0.35` と沈みの傾き `±(1 − dip)·0.5` から `N = normalize(−g, 1)`。束の端 14% は `edgeDark` で暗くして隣の束の下に潜る影にする。
- **繊維の縞**: 束を 9 本に分け、`stripe = 0.75 + 0.25·sin(2π·fr + wave)`。wave は値ノイズで繊維をわずかに蛇行させる。束ごとの明るさ `rnd = 0.88 + 0.24·hash`。
- **光源**: `Lp = (cursor, 0.55·W)`。距離減衰 `att = 1/(1 + 3·(dist/W)²)`。拡散 `nl = max(N·L, 0)·(0.4 + 0.6·att)`。
- **異方性(Kajiya-Kay)**: 繊維接線 T(横糸は (1,0)、縦糸は (0,1))と半ベクトル H で `an = (1 − (T·H)²)^(90/2)`。`col += (0.42, 0.43, 0.46)·an·nl·att·stripe·edgeDark·(0.5 + 0.5·rnd)`。
- **クリアコート**: `coat = (N·H)^160`、`col += 0.55·coat·att`。フレネル `(1 − N·V)^4·0.25` を薄く、上からの環境反射 `smoothstep(−.2, 1, N.y)·0.03` を足す。
- 基本色 `(0.04, 0.042, 0.047)·rnd·stripe` に `(0.35 + 0.9·nl)·(0.55 + 0.45·edgeDark)` を掛ける。最後に `pow(col, 1/1.08)` とハッシュの粒 ±0.003。
- CSS で `.hero::after` に2枚の黒グラデーションを重ねる。左から右へ 60% → 25%(32%位置)→ 0%(55%位置)と、ヘッダーの技法名を読ませるための上から下へ 55% → 0%(高さ13%まで)。

```glsl
float m=mod(cell.x-cell.y,4.); bool horiz=m<2.;
float along=horiz?(m+f.x)*.5:((3.-m)+f.y)*.5; float across=horiz?f.y:f.x;
vec2 T=horiz?vec2(1.,0.):vec2(0.,1.);
float th=dot(vec3(T,0.),H); float an=pow(sqrt(max(0.,1.-th*th)),uAniso);
col += vec3(.42,.43,.46)*an*nl*att*stripe*edgeDark;
col += vec3(.9,.92,.95)*pow(max(dot(N,H),0.),uCoat)*.55*att;
```

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --obsidian | #000000 | 地。canvas の外側と nogl 時の背景 |
| 繊維の基本色 | #0a0b0c 相当 | シェーダーの base。縞と束ごとの乱数で ±12% 振る |
| --chalk | #e2e8f0 | ヘッダーの工房名、クレジット |
| #ffffff | — | 見出し「Twill」 |
| --fog | #b3b3b5 | 見出し下の日本語、ステータス文字 |
| --ash | #8b8b8f | ヘッダー補助と本文と操作説明の灰色 |
| --signal | #3ddc84 | 稼働中を示す 8px の点。画面で唯一の色 |
| --graphite | #232323 | 予備の罫線色 |

## Typography
- 見出し: Inter 900、`clamp(44px, 7.4vw, 112px)`、line-height 0.98、letter-spacing −0.035em。
- 見出し下: Noto Sans JP 300、`clamp(15px, 1.3vw, 19px)`、letter-spacing 0.06em、line-height 1.6、見出しとの間 18px。2文を `<br>` で分け、1文1行にする。`.copy` の最大幅は 24em(モバイルは制限なし)。
- ステータス: JetBrains Mono 400 12px、letter-spacing 0.08em、大文字。緑の点は `box-shadow` で 10px の光。
- 本文: Noto Sans JP 400、`clamp(13px, 1.05vw, 15px)`。
- ラベル: JetBrains Mono 400、11–12px。

## Spacing & Layout
- hero `min-height: 100svh`、3行グリッド。canvas は背面全面、その上に `.hero::after` のグラデーション。
- 余白: 横 `clamp(20px, 5vw, 72px)`、上 `clamp(20px, 3vw, 40px)`、下 `clamp(18px, 2.6vw, 32px)`。ステータスの点と文字の間 10px、本文の前 14px。モバイル左右 18px。
- 見出しは中央行の左、垂直中央。ステータスは左下、クレジットは右下。
- breakpoint 760px: ヘッダー右を消し、フッターを縦積み、ステータスの本文を折り返す。

## Motion
- 光源はカーソルへ 7%/フレームで追従。カーソル無し・タッチ端末では (左から 62% ± 25%, 下から 60% ± 30%) の楕円を周期約33秒 / 27秒で回る。
- 織り自体は動かない。動くのは光だけ。
- rAF 1本。IntersectionObserver と visibilitychange で画面外停止。
- `prefers-reduced-motion: reduce`: 光源を (左から65%, 下から70%) に固定して1フレームだけ描く。カーソル移動時のみ再描画。

## Components
- hero: 背面 canvas(`aria-hidden`)+黒グラデーション+前面テキスト。WebGL 不可時は `.nogl` で斜めの繰り返しグラデーションに落とす。
- header: 左に工房名、右に技法名。
- copy: 欧文見出し1語+日本語2文。
- status: 緑の点 + `WORKSHOP OPEN` + 短文1つ。
- footer tag: `VALE / PARTS 027 / カーボン` と操作説明1行(タッチ端末では差し替え)。

## Do / Don't
- Do: 束の幅は 10–18px。細すぎると縞がモアレになり、太すぎると籠に見える。
- Do: 光源は1つ。異方性の筋は光源の周りだけで出す(att を掛ける)。
- Do: 文字の下には黒のグラデーションを重ねる。canvas より後に描かれる `::after` に置く(`::before` だと canvas の下に隠れる)。
- Don't: 織りに色を付けない。カーボンは無彩色のまま。
- Don't: 織りをアニメーションさせない。動くのは光だけ。
- Don't: 緑の点以外に色を足さない。

## References
- Trunk: 無彩色の暗い制御室に緑の信号を1点だけ置く構成を借りた。UI の罫線やカードは捨て、素材そのものを背景にした。
- Portal: 黒地に weight 900 の重い見出しを置く型を借りた。紫の光は使わず、見出しは白1色にして素材の反射だけを光らせた。

## Usage
1. `<canvas id="gl">` を hero の背面に置き、`<script>` ブロック全体を移植する。
2. 文字を乗せる側に `.hero::after` の横向きグラデーションを向ける(右寄せなら `270deg`)。上端のグラデーションはヘッダーを置かないなら消してよい。
3. 色を変えるときはシェーダーの `base` と2つのハイライト色を書き換える(例: 金色のケブラー風なら base を (0.12, 0.09, 0.03) に)。
4. WebGL 不可時の見た目は `.nogl` の CSS で用意する。

| パラメータ | 既定 | 意味 |
|---|---|---|
| tow | 15 / 11(モバイル) | 繊維束の幅(CSS px) |
| fibers | 9 | 束の中の縞の本数 |
| lightZ | 0.55 | 光源の高さ(画面幅比)。低いほど筋が鋭い |
| follow | 0.07 | 光源の追従率 |
| aniso | 90 | 異方性ハイライトの鋭さ(30–200) |
| coat | 160 | クリアコートの鋭さ(60–400) |
| dprMax | 1.5 | 表示解像度の上限 |
